@visactor/vtable-sheet 1.22.7 → 1.22.8-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/components/sheet-tab-event-handler.js +3 -2
- package/cjs/components/sheet-tab-event-handler.js.map +1 -1
- package/cjs/components/vtable-sheet.d.ts +2 -1
- package/cjs/components/vtable-sheet.js +9 -1
- package/cjs/components/vtable-sheet.js.map +1 -1
- package/cjs/core/WorkSheet.d.ts +1 -1
- package/cjs/core/WorkSheet.js.map +1 -1
- package/cjs/core/table-plugins.js +7 -5
- package/cjs/core/table-plugins.js.map +1 -1
- package/cjs/formula/cell-highlight-manager.d.ts +1 -0
- package/cjs/formula/cell-highlight-manager.js +27 -22
- package/cjs/formula/cell-highlight-manager.js.map +1 -1
- package/cjs/formula/cross-sheet-data-synchronizer.d.ts +48 -0
- package/cjs/formula/cross-sheet-data-synchronizer.js +159 -0
- package/cjs/formula/cross-sheet-data-synchronizer.js.map +1 -0
- package/cjs/formula/cross-sheet-formula-handler.d.ts +58 -0
- package/cjs/formula/cross-sheet-formula-handler.js +240 -0
- package/cjs/formula/cross-sheet-formula-handler.js.map +1 -0
- package/cjs/formula/cross-sheet-formula-manager.d.ts +52 -0
- package/cjs/formula/cross-sheet-formula-manager.js +235 -0
- package/cjs/formula/cross-sheet-formula-manager.js.map +1 -0
- package/cjs/formula/cross-sheet-formula-validator.d.ts +56 -0
- package/cjs/formula/cross-sheet-formula-validator.js +271 -0
- package/cjs/formula/cross-sheet-formula-validator.js.map +1 -0
- package/cjs/formula/formula-engine.d.ts +4 -1
- package/cjs/formula/formula-engine.js +132 -25
- package/cjs/formula/formula-engine.js.map +1 -1
- package/cjs/formula/formula-paste-processor.d.ts +3 -3
- package/cjs/formula/formula-paste-processor.js.map +1 -1
- package/cjs/formula/formula-reference-adjustor.d.ts +1 -1
- package/cjs/formula/formula-reference-adjustor.js.map +1 -1
- package/cjs/formula/index.d.ts +8 -0
- package/cjs/formula/index.js +40 -3
- package/cjs/formula/index.js.map +1 -1
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +1 -1
- package/cjs/index.js.map +1 -1
- package/cjs/managers/formula-manager.d.ts +17 -2
- package/cjs/managers/formula-manager.js +150 -12
- package/cjs/managers/formula-manager.js.map +1 -1
- package/cjs/styles/menu.js +2 -1
- package/cjs/styles/sheet-tab.js +1 -2
- package/cjs/tools/index.js +2 -1
- package/dist/vtable-sheet.js +11322 -331
- package/dist/vtable-sheet.min.js +1 -1
- package/es/components/sheet-tab-event-handler.js +3 -2
- package/es/components/sheet-tab-event-handler.js.map +1 -1
- package/es/components/vtable-sheet.d.ts +2 -1
- package/es/components/vtable-sheet.js +9 -1
- package/es/components/vtable-sheet.js.map +1 -1
- package/es/core/WorkSheet.d.ts +1 -1
- package/es/core/WorkSheet.js.map +1 -1
- package/es/core/table-plugins.js +7 -5
- package/es/core/table-plugins.js.map +1 -1
- package/es/formula/cell-highlight-manager.d.ts +1 -0
- package/es/formula/cell-highlight-manager.js +27 -22
- package/es/formula/cell-highlight-manager.js.map +1 -1
- package/es/formula/cross-sheet-data-synchronizer.d.ts +48 -0
- package/es/formula/cross-sheet-data-synchronizer.js +151 -0
- package/es/formula/cross-sheet-data-synchronizer.js.map +1 -0
- package/es/formula/cross-sheet-formula-handler.d.ts +58 -0
- package/es/formula/cross-sheet-formula-handler.js +236 -0
- package/es/formula/cross-sheet-formula-handler.js.map +1 -0
- package/es/formula/cross-sheet-formula-manager.d.ts +52 -0
- package/es/formula/cross-sheet-formula-manager.js +227 -0
- package/es/formula/cross-sheet-formula-manager.js.map +1 -0
- package/es/formula/cross-sheet-formula-validator.d.ts +56 -0
- package/es/formula/cross-sheet-formula-validator.js +263 -0
- package/es/formula/cross-sheet-formula-validator.js.map +1 -0
- package/es/formula/formula-engine.d.ts +4 -1
- package/es/formula/formula-engine.js +132 -25
- package/es/formula/formula-engine.js.map +1 -1
- package/es/formula/formula-paste-processor.d.ts +3 -3
- package/es/formula/formula-paste-processor.js.map +1 -1
- package/es/formula/formula-reference-adjustor.d.ts +1 -1
- package/es/formula/formula-reference-adjustor.js.map +1 -1
- package/es/formula/index.d.ts +8 -0
- package/es/formula/index.js +8 -0
- package/es/formula/index.js.map +1 -1
- package/es/index.d.ts +1 -1
- package/es/index.js +1 -1
- package/es/index.js.map +1 -1
- package/es/managers/formula-manager.d.ts +17 -2
- package/es/managers/formula-manager.js +152 -11
- package/es/managers/formula-manager.js.map +1 -1
- package/es/styles/menu.js +2 -1
- package/es/styles/sheet-tab.js +1 -2
- package/es/tools/index.js +2 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/formula/cell-highlight-manager.ts"],"names":[],"mappings":"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","file":"cell-highlight-manager.js","sourcesContent":["import type { WorkSheet } from '../core/WorkSheet';\nimport type VTableSheet from '../components/vtable-sheet';\nimport type { CellCoord } from '../ts-types';\n\ninterface HighlightedCell {\n row: number;\n col: number;\n color: string;\n}\n\nexport class CellHighlightManager {\n private sheet: VTableSheet;\n private highlightedCells: Map<string, HighlightedCell> = new Map();\n // /** 目前还没有自定义样式的功能 这个逻辑不需要 */\n // private originalBorderStyles: Map<string, any> = new Map(); // 保存原始边框样式\n private colors = [\n '#4A90E2', // 蓝色\n '#50C878', // 绿色\n '#FF6B6B', // 红色\n '#FFD93D', // 黄色\n '#6BCB77', // 浅绿\n '#9B59B6', // 紫色\n '#FF8C42', // 橙色\n '#00BCD4' // 青色\n ];\n private colorIndex = 0;\n\n constructor(sheet: VTableSheet) {\n this.sheet = sheet;\n }\n\n /**\n * 解析公式中的单元格引用(包括范围引用)\n */\n parseCellReferences(\n formula: string\n ): Array<{ address: string; coords: CellCoord[]; color: string; isRange: boolean }> {\n const references: Array<{ address: string; coords: CellCoord[]; color: string; isRange: boolean }> = [];\n\n // 匹配单元格引用的正则表达式(包括范围引用)\n const cellRefRegex = /(\\$?[A-Z]+\\$?\\d+(?::\\$?[A-Z]+\\$?\\d+)?)/gi;\n\n const matches = formula.match(cellRefRegex);\n if (!matches) {\n return references;\n }\n\n const activeSheet = this.sheet.getActiveSheet();\n if (!activeSheet) {\n return references;\n }\n\n const uniqueRefs = new Set<string>();\n this.colorIndex = 0;\n\n matches.forEach(match => {\n const normalizedRef = match.replace(/\\$/g, '').toUpperCase();\n\n if (!uniqueRefs.has(normalizedRef)) {\n uniqueRefs.add(normalizedRef);\n\n try {\n const isRange = normalizedRef.includes(':');\n let coords: CellCoord[] = [];\n\n if (isRange) {\n // 解析范围引用,如 A1:A4\n coords = this.parseRangeReference(normalizedRef, activeSheet);\n } else {\n // 解析单个单元格引用,如 A1\n const coord = activeSheet.coordFromAddress(normalizedRef);\n coords = [coord];\n }\n\n if (coords.length > 0) {\n const color = this.colors[this.colorIndex % this.colors.length];\n this.colorIndex++;\n\n references.push({\n address: normalizedRef,\n coords: coords,\n color: color,\n isRange: isRange\n });\n }\n } catch (e) {\n // 忽略无效的单元格引用\n console.warn(`Invalid cell reference: ${normalizedRef}`, e);\n }\n }\n });\n\n return references;\n }\n\n /**\n * 解析范围引用,如 A1:A4\n */\n private parseRangeReference(rangeRef: string, activeSheet: WorkSheet): CellCoord[] {\n const parts = rangeRef.split(':');\n if (parts.length !== 2) {\n throw new Error(`Invalid range reference: ${rangeRef}`);\n }\n\n const startCoord = activeSheet.coordFromAddress(parts[0]);\n const endCoord = activeSheet.coordFromAddress(parts[1]);\n\n const coords: CellCoord[] = [];\n\n // 生成范围内的所有单元格坐标\n const startRow = Math.min(startCoord.row, endCoord.row);\n const endRow = Math.max(startCoord.row, endCoord.row);\n const startCol = Math.min(startCoord.col, endCoord.col);\n const endCol = Math.max(startCoord.col, endCoord.col);\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n coords.push({ row, col });\n }\n }\n\n return coords;\n }\n\n /**\n * 高亮公式中引用的单元格\n */\n highlightFormulaCells(formula: string): void {\n // 清除之前的高亮\n this.clearHighlights();\n\n const references = this.parseCellReferences(formula);\n\n if (references.length === 0) {\n return;\n }\n\n const activeSheet = this.sheet.getActiveSheet();\n if (!activeSheet) {\n return;\n }\n\n // 应用高亮\n references.forEach(ref => {\n ref.coords.forEach(coord => {\n const key = `${coord.row}-${coord.col}`;\n\n // 保存高亮信息\n this.highlightedCells.set(key, {\n row: coord.row,\n col: coord.col,\n color: ref.color\n });\n\n // 应用高亮样式\n this.applyCellHighlight(activeSheet, coord, ref.color);\n });\n });\n }\n\n /**\n * 应用单元格高亮\n * 通过修改单元格的边框样式实现\n */\n private applyCellHighlight(sheet: WorkSheet, coord: CellCoord, color: string): void {\n const table = (sheet as any).tableInstance;\n if (!table || !table.scenegraph) {\n return;\n }\n\n try {\n const key = `${coord.row}-${coord.col}`;\n\n // // 保存原始样式\n // if (!this.originalBorderStyles.has(key)) {\n // const originalStyle = table.getCellStyle(coord.col, coord.row);\n // this.originalBorderStyles.set(key, originalStyle);\n // }\n\n // 创建高亮样式\n const highlightStyle = {\n // ...table._getCellStyle(coord.col, coord.row),\n borderColor: [color, color, color, color],\n borderLineWidth: [4, 4, 4, 4],\n borderLineDash: [\n [4, 4],\n [4, 4],\n [4, 4],\n [4, 4]\n ],\n padding: [8, 8, 8, 8]\n };\n\n // 注册自定义样式\n const styleId = `highlight-${key}`;\n table.registerCustomCellStyle(styleId, highlightStyle);\n\n // 应用样式到单元格\n table.arrangeCustomCellStyle({ col: coord.col, row: coord.row }, styleId, false);\n } catch (e) {\n console.error('applyCellHighlight: 错误', e);\n }\n }\n\n /**\n * 清除所有高亮\n */\n clearHighlights(): void {\n const activeSheet = this.sheet.getActiveSheet();\n if (!activeSheet) {\n return;\n }\n\n const table = (activeSheet as any).tableInstance;\n if (!table || !table.scenegraph) {\n return;\n }\n\n this.highlightedCells.forEach(info => {\n try {\n const key = `${info.row}-${info.col}`;\n const styleId = `highlight-${key}`;\n\n // 移除高亮样式\n table.arrangeCustomCellStyle({ col: info.col, row: info.row }, null, false);\n\n // // 恢复原始样式\n // const originalStyle = this.originalBorderStyles.get(key);\n // if (originalStyle) {\n // table.registerCustomCellStyle(styleId, originalStyle);\n // table.arrangeCustomCellStyle({ col: info.col, row: info.row }, styleId, true);\n // }\n } catch (e) {\n console.warn(`Failed to clear highlight at ${info.row},${info.col}:`, e);\n }\n });\n\n this.highlightedCells.clear();\n // this.originalBorderStyles.clear();\n this.colorIndex = 0;\n }\n\n /**\n * 获取单元格的高亮颜色\n */\n getCellHighlightColor(coord: CellCoord): string | null {\n const key = `${coord.row}-${coord.col}`;\n const info = this.highlightedCells.get(key);\n return info ? info.color : null;\n }\n\n /**\n * 获取高亮的单元格列表\n */\n getHighlightedCells(): Array<{ coord: CellCoord; color: string }> {\n return Array.from(this.highlightedCells.values()).map(info => ({\n coord: { row: info.row, col: info.col },\n color: info.color\n }));\n }\n\n /**\n * 获取彩色公式文本\n */\n getColorizedFormula(formula: string): Array<{ text: string; color?: string }> {\n const references = this.parseCellReferences(formula);\n const parts: Array<{ text: string; color?: string }> = [];\n\n if (references.length === 0) {\n return [{ text: formula }];\n }\n\n let lastIndex = 0;\n const colorMap = new Map<string, string>();\n references.forEach(ref => {\n colorMap.set(ref.address.toUpperCase(), ref.color);\n });\n\n const regex = /(\\$?[A-Z]+\\$?\\d+)/gi;\n let match;\n\n while ((match = regex.exec(formula)) !== null) {\n if (match.index > lastIndex) {\n parts.push({ text: formula.substring(lastIndex, match.index) });\n }\n\n const normalizedRef = match[0].replace(/\\$/g, '').toUpperCase();\n const color = colorMap.get(normalizedRef);\n parts.push({\n text: match[0],\n color: color\n });\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < formula.length) {\n parts.push({ text: formula.substring(lastIndex) });\n }\n\n return parts;\n }\n\n /**\n * 销毁管理器\n */\n release(): void {\n this.clearHighlights();\n this.highlightedCells.clear();\n // this.originalBorderStyles.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/formula/cell-highlight-manager.ts"],"names":[],"mappings":"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","file":"cell-highlight-manager.js","sourcesContent":["import type { WorkSheet } from '../core/WorkSheet';\nimport type VTableSheet from '../components/vtable-sheet';\nimport type { CellCoord } from '../ts-types';\n\ninterface HighlightedCell {\n row: number;\n col: number;\n color: string;\n}\n\nexport class CellHighlightManager {\n private sheet: VTableSheet;\n private highlightedCells: Map<string, HighlightedCell> = new Map();\n // /** 目前还没有自定义样式的功能 这个逻辑不需要 */\n // private originalBorderStyles: Map<string, any> = new Map(); // 保存原始边框样式\n private colors = [\n '#4A90E2', // 蓝色\n '#50C878', // 绿色\n '#FF6B6B', // 红色\n '#FFD93D', // 黄色\n '#6BCB77', // 浅绿\n '#9B59B6', // 紫色\n '#FF8C42', // 橙色\n '#00BCD4' // 青色\n ];\n private colorIndex = 0;\n\n constructor(sheet: VTableSheet) {\n this.sheet = sheet;\n }\n\n /**\n * 解析公式中的单元格引用(包括范围引用)\n */\n parseCellReferences(formula: string): Array<{\n address: string;\n coords: CellCoord[];\n color: string;\n isRange: boolean;\n sheetName?: string;\n }> {\n const references: Array<{\n address: string;\n coords: CellCoord[];\n color: string;\n isRange: boolean;\n sheetName?: string;\n }> = [];\n\n // 更简单的跨sheet引用匹配方法\n // 匹配模式:Sheet1!A1, 'Sheet Name'!A1, A1, A1:B2, Sheet1!A1:B2\n const cellRefRegex = /(?:([']?[^!'\\s]+[']?)!)?(\\$?[A-Z]+\\$?\\d+(?::\\$?[A-Z]+\\$?\\d+)?)/g;\n\n const uniqueRefs = new Map<string, { sheetName?: string; cellRef: string }>();\n this.colorIndex = 0;\n\n let match;\n while ((match = cellRefRegex.exec(formula)) !== null) {\n // 解析跨sheet引用\n const sheetNamePart = match[1];\n const cellRef = match[2];\n\n let sheetName: string | undefined;\n if (sheetNamePart) {\n sheetName = sheetNamePart.replace(/'/g, ''); // 移除可能的引号\n }\n\n const normalizedCellRef = cellRef.replace(/\\$/g, '').toUpperCase();\n const uniqueKey = sheetName ? `${sheetName}!${normalizedCellRef}` : normalizedCellRef;\n\n if (!uniqueRefs.has(uniqueKey)) {\n uniqueRefs.set(uniqueKey, { sheetName, cellRef: normalizedCellRef });\n\n try {\n const isRange = normalizedCellRef.includes(':');\n let coords: CellCoord[] = [];\n\n // 获取目标sheet\n const targetSheet = sheetName ? this.sheet.getSheetByName(sheetName) : this.sheet.getActiveSheet();\n if (!targetSheet) {\n console.warn(`Sheet not found: ${sheetName || 'active sheet'}`);\n continue;\n }\n\n if (isRange) {\n // 解析范围引用,如 A1:A4\n coords = this.parseRangeReference(normalizedCellRef, targetSheet);\n } else {\n // 解析单个单元格引用,如 A1\n const coord = targetSheet.coordFromAddress(normalizedCellRef);\n coords = [coord];\n }\n\n if (coords.length > 0) {\n const color = this.colors[this.colorIndex % this.colors.length];\n this.colorIndex++;\n\n references.push({\n address: uniqueKey,\n coords: coords,\n color: color,\n isRange: isRange,\n sheetName: sheetName\n });\n }\n } catch (e) {\n // 忽略无效的单元格引用\n console.warn(`Invalid cell reference: ${uniqueKey}`, e);\n }\n }\n }\n\n return references;\n }\n\n /**\n * 解析范围引用,如 A1:A4\n */\n private parseRangeReference(rangeRef: string, activeSheet: WorkSheet): CellCoord[] {\n const parts = rangeRef.split(':');\n if (parts.length !== 2) {\n throw new Error(`Invalid range reference: ${rangeRef}`);\n }\n\n const startCoord = activeSheet.coordFromAddress(parts[0]);\n const endCoord = activeSheet.coordFromAddress(parts[1]);\n\n const coords: CellCoord[] = [];\n\n // 生成范围内的所有单元格坐标\n const startRow = Math.min(startCoord.row, endCoord.row);\n const endRow = Math.max(startCoord.row, endCoord.row);\n const startCol = Math.min(startCoord.col, endCoord.col);\n const endCol = Math.max(startCoord.col, endCoord.col);\n\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n coords.push({ row, col });\n }\n }\n\n return coords;\n }\n\n /**\n * 高亮公式中引用的单元格(支持跨sheet)\n */\n highlightFormulaCells(formula: string): void {\n // 清除之前的高亮\n this.clearHighlights();\n\n const references = this.parseCellReferences(formula);\n\n if (references.length === 0) {\n return;\n }\n\n // 应用高亮 - 支持跨sheet\n references.forEach(ref => {\n // 获取目标sheet\n const targetSheet = ref.sheetName ? this.sheet.getSheetByName(ref.sheetName) : this.sheet.getActiveSheet();\n\n if (!targetSheet) {\n console.warn(`Sheet not found for highlighting: ${ref.sheetName || 'active sheet'}`);\n return;\n }\n\n ref.coords.forEach(coord => {\n // 使用包含sheet名称的唯一key\n const sheetPrefix = ref.sheetName ? `${ref.sheetName}!` : '';\n const key = `${sheetPrefix}${coord.row}-${coord.col}`;\n\n // 保存高亮信息\n this.highlightedCells.set(key, {\n row: coord.row,\n col: coord.col,\n color: ref.color\n });\n\n // 应用高亮样式到正确的sheet\n this.applyCellHighlight(targetSheet, coord, ref.color);\n });\n });\n }\n\n /**\n * 应用单元格高亮\n * 通过修改单元格的边框样式实现\n */\n private applyCellHighlight(sheet: WorkSheet, coord: CellCoord, color: string): void {\n const table = (sheet as any).tableInstance;\n if (!table || !table.scenegraph) {\n return;\n }\n\n try {\n const key = `${coord.row}-${coord.col}`;\n\n // // 保存原始样式\n // if (!this.originalBorderStyles.has(key)) {\n // const originalStyle = table.getCellStyle(coord.col, coord.row);\n // this.originalBorderStyles.set(key, originalStyle);\n // }\n\n // 创建高亮样式\n const highlightStyle = {\n // ...table._getCellStyle(coord.col, coord.row),\n borderColor: [color, color, color, color],\n borderLineWidth: [4, 4, 4, 4],\n borderLineDash: [\n [4, 4],\n [4, 4],\n [4, 4],\n [4, 4]\n ],\n padding: [8, 8, 8, 8]\n };\n\n // 注册自定义样式\n const styleId = `highlight-${key}`;\n table.registerCustomCellStyle(styleId, highlightStyle);\n\n // 应用样式到单元格\n table.arrangeCustomCellStyle({ col: coord.col, row: coord.row }, styleId, false);\n } catch (e) {\n console.error('applyCellHighlight: 错误', e);\n }\n }\n\n /**\n * 清除所有高亮\n */\n clearHighlights(): void {\n const activeSheet = this.sheet.getActiveSheet();\n if (!activeSheet) {\n return;\n }\n\n const table = (activeSheet as any).tableInstance;\n if (!table || !table.scenegraph) {\n return;\n }\n\n this.highlightedCells.forEach(info => {\n try {\n // 移除高亮样式\n table.arrangeCustomCellStyle({ col: info.col, row: info.row }, null, false);\n\n // // 恢复原始样式\n // const originalStyle = this.originalBorderStyles.get(key);\n // if (originalStyle) {\n // table.registerCustomCellStyle(styleId, originalStyle);\n // table.arrangeCustomCellStyle({ col: info.col, row: info.row }, styleId, true);\n // }\n } catch (e) {\n console.warn(`Failed to clear highlight at ${info.row},${info.col}:`, e);\n }\n });\n\n this.highlightedCells.clear();\n // this.originalBorderStyles.clear();\n this.colorIndex = 0;\n }\n\n /**\n * 获取单元格的高亮颜色\n */\n getCellHighlightColor(coord: CellCoord): string | null {\n const key = `${coord.row}-${coord.col}`;\n const info = this.highlightedCells.get(key);\n return info ? info.color : null;\n }\n\n /**\n * 获取高亮的单元格列表\n */\n getHighlightedCells(): Array<{ coord: CellCoord; color: string }> {\n return Array.from(this.highlightedCells.values()).map(info => ({\n coord: { row: info.row, col: info.col },\n color: info.color\n }));\n }\n\n /**\n * 获取彩色公式文本\n */\n getColorizedFormula(formula: string): Array<{ text: string; color?: string }> {\n const references = this.parseCellReferences(formula);\n const parts: Array<{ text: string; color?: string }> = [];\n\n if (references.length === 0) {\n return [{ text: formula }];\n }\n\n let lastIndex = 0;\n const colorMap = new Map<string, string>();\n references.forEach(ref => {\n colorMap.set(ref.address.toUpperCase(), ref.color);\n });\n\n const regex = /(\\$?[A-Z]+\\$?\\d+)/gi;\n let match;\n\n while ((match = regex.exec(formula)) !== null) {\n if (match.index > lastIndex) {\n parts.push({ text: formula.substring(lastIndex, match.index) });\n }\n\n const normalizedRef = match[0].replace(/\\$/g, '').toUpperCase();\n const color = colorMap.get(normalizedRef);\n parts.push({\n text: match[0],\n color: color\n });\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < formula.length) {\n parts.push({ text: formula.substring(lastIndex) });\n }\n\n return parts;\n }\n\n /**\n * 销毁管理器\n */\n release(): void {\n this.clearHighlights();\n this.highlightedCells.clear();\n // this.originalBorderStyles.clear();\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { FormulaCell } from '../ts-types/formula';
|
|
2
|
+
import type { FormulaEngine } from './formula-engine';
|
|
3
|
+
import type { CrossSheetFormulaManager } from './cross-sheet-formula-manager';
|
|
4
|
+
export interface DataChangeEvent {
|
|
5
|
+
sheet: string;
|
|
6
|
+
cells: FormulaCell[];
|
|
7
|
+
oldValues: any[];
|
|
8
|
+
newValues: any[];
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SyncOptions {
|
|
12
|
+
immediate: boolean;
|
|
13
|
+
batchSize: number;
|
|
14
|
+
timeout: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class CrossSheetDataSynchronizer {
|
|
17
|
+
private formulaEngine;
|
|
18
|
+
private crossSheetManager;
|
|
19
|
+
private changeQueue;
|
|
20
|
+
private isSyncing;
|
|
21
|
+
private syncTimer;
|
|
22
|
+
private options;
|
|
23
|
+
private listeners;
|
|
24
|
+
constructor(formulaEngine: FormulaEngine, crossSheetManager: CrossSheetFormulaManager);
|
|
25
|
+
registerDataChange(sheet: string, cells: FormulaCell[], oldValues: any[], newValues: any[]): void;
|
|
26
|
+
private scheduleSync;
|
|
27
|
+
private processChanges;
|
|
28
|
+
private groupChangesBySheet;
|
|
29
|
+
private syncSheetChanges;
|
|
30
|
+
getCrossSheetDependencies(): Map<string, string[]>;
|
|
31
|
+
validateCrossSheetReferences(): {
|
|
32
|
+
valid: boolean;
|
|
33
|
+
errors: string[];
|
|
34
|
+
};
|
|
35
|
+
private detectCircularDependencies;
|
|
36
|
+
addDataChangeListener(sheet: string, listener: (event: DataChangeEvent) => void): void;
|
|
37
|
+
removeDataChangeListener(sheet: string, listener: (event: DataChangeEvent) => void): void;
|
|
38
|
+
private emitDataChange;
|
|
39
|
+
forceSync(): Promise<void>;
|
|
40
|
+
clearSyncQueue(): void;
|
|
41
|
+
getSyncStatus(): {
|
|
42
|
+
pendingChanges: number;
|
|
43
|
+
isSyncing: boolean;
|
|
44
|
+
lastSyncTime: number | null;
|
|
45
|
+
};
|
|
46
|
+
updateSyncOptions(options: Partial<SyncOptions>): void;
|
|
47
|
+
destroy(): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __awaiter = this && this.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
4
|
+
return new (P || (P = Promise))((function(resolve, reject) {
|
|
5
|
+
function fulfilled(value) {
|
|
6
|
+
try {
|
|
7
|
+
step(generator.next(value));
|
|
8
|
+
} catch (e) {
|
|
9
|
+
reject(e);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function rejected(value) {
|
|
13
|
+
try {
|
|
14
|
+
step(generator.throw(value));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function step(result) {
|
|
20
|
+
var value;
|
|
21
|
+
result.done ? resolve(result.value) : (value = result.value, value instanceof P ? value : new P((function(resolve) {
|
|
22
|
+
resolve(value);
|
|
23
|
+
}))).then(fulfilled, rejected);
|
|
24
|
+
}
|
|
25
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
Object.defineProperty(exports, "__esModule", {
|
|
30
|
+
value: !0
|
|
31
|
+
}), exports.CrossSheetDataSynchronizer = void 0;
|
|
32
|
+
|
|
33
|
+
class CrossSheetDataSynchronizer {
|
|
34
|
+
constructor(formulaEngine, crossSheetManager) {
|
|
35
|
+
this.changeQueue = [], this.isSyncing = !1, this.syncTimer = null, this.options = {
|
|
36
|
+
immediate: !1,
|
|
37
|
+
batchSize: 100,
|
|
38
|
+
timeout: 50
|
|
39
|
+
}, this.listeners = new Map, this.formulaEngine = formulaEngine, this.crossSheetManager = crossSheetManager;
|
|
40
|
+
}
|
|
41
|
+
registerDataChange(sheet, cells, oldValues, newValues) {
|
|
42
|
+
const event = {
|
|
43
|
+
sheet: sheet,
|
|
44
|
+
cells: cells,
|
|
45
|
+
oldValues: oldValues,
|
|
46
|
+
newValues: newValues,
|
|
47
|
+
timestamp: Date.now()
|
|
48
|
+
};
|
|
49
|
+
this.changeQueue.push(event), this.options.immediate ? this.processChanges() : this.scheduleSync();
|
|
50
|
+
}
|
|
51
|
+
scheduleSync() {
|
|
52
|
+
this.syncTimer && clearTimeout(this.syncTimer), this.syncTimer = setTimeout((() => {
|
|
53
|
+
this.processChanges();
|
|
54
|
+
}), this.options.timeout);
|
|
55
|
+
}
|
|
56
|
+
processChanges() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
58
|
+
if (!this.isSyncing && 0 !== this.changeQueue.length) {
|
|
59
|
+
this.isSyncing = !0;
|
|
60
|
+
try {
|
|
61
|
+
const batch = this.changeQueue.splice(0, this.options.batchSize), changesBySheet = this.groupChangesBySheet(batch);
|
|
62
|
+
for (const [targetSheet, changes] of changesBySheet.entries()) yield this.syncSheetChanges(targetSheet, changes);
|
|
63
|
+
for (const event of batch) this.emitDataChange(event);
|
|
64
|
+
} catch (error) {} finally {
|
|
65
|
+
this.isSyncing = !1, this.changeQueue.length > 0 && this.scheduleSync();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
groupChangesBySheet(events) {
|
|
71
|
+
const groups = new Map;
|
|
72
|
+
for (const event of events) {
|
|
73
|
+
const existing = groups.get(event.sheet) || [];
|
|
74
|
+
existing.push(event), groups.set(event.sheet, existing);
|
|
75
|
+
}
|
|
76
|
+
return groups;
|
|
77
|
+
}
|
|
78
|
+
syncSheetChanges(targetSheet, changes) {
|
|
79
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
80
|
+
const allChangedCells = [], allOldValues = [], allNewValues = [];
|
|
81
|
+
for (const change of changes) allChangedCells.push(...change.cells), allOldValues.push(...change.oldValues),
|
|
82
|
+
allNewValues.push(...change.newValues);
|
|
83
|
+
yield this.crossSheetManager.updateCrossSheetReferences(targetSheet, allChangedCells);
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
getCrossSheetDependencies() {
|
|
87
|
+
const dependencies = new Map, allSheets = this.formulaEngine.getAllSheets();
|
|
88
|
+
for (const sheetInfo of allSheets) {
|
|
89
|
+
const targetSheets = this.crossSheetManager.getCrossSheetDependencies(sheetInfo.key).map((dep => dep.precedentSheet));
|
|
90
|
+
dependencies.set(sheetInfo.key, targetSheets);
|
|
91
|
+
}
|
|
92
|
+
return dependencies;
|
|
93
|
+
}
|
|
94
|
+
validateCrossSheetReferences() {
|
|
95
|
+
const errors = [], allSheets = this.formulaEngine.getAllSheets();
|
|
96
|
+
for (const sheetInfo of allSheets) {
|
|
97
|
+
const validation = this.crossSheetManager.validateCrossSheetReferences(sheetInfo.key);
|
|
98
|
+
validation.valid || errors.push(...validation.errors);
|
|
99
|
+
const circularDeps = this.detectCircularDependencies(sheetInfo.key, new Set);
|
|
100
|
+
circularDeps.length > 0 && errors.push(`Circular dependency detected in sheet ${sheetInfo.key}: ${circularDeps.join(" -> ")}`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
valid: 0 === errors.length,
|
|
104
|
+
errors: errors
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
detectCircularDependencies(sheet, visited) {
|
|
108
|
+
if (visited.has(sheet)) return [ sheet ];
|
|
109
|
+
visited.add(sheet);
|
|
110
|
+
const dependencies = this.crossSheetManager.getCrossSheetDependencies(sheet);
|
|
111
|
+
for (const dep of dependencies) {
|
|
112
|
+
const cycle = this.detectCircularDependencies(dep.precedentSheet, new Set(visited));
|
|
113
|
+
if (cycle.length > 0) return [ sheet, ...cycle ];
|
|
114
|
+
}
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
addDataChangeListener(sheet, listener) {
|
|
118
|
+
this.listeners.has(sheet) || this.listeners.set(sheet, new Set), this.listeners.get(sheet).add(listener);
|
|
119
|
+
}
|
|
120
|
+
removeDataChangeListener(sheet, listener) {
|
|
121
|
+
const listeners = this.listeners.get(sheet);
|
|
122
|
+
listeners && (listeners.delete(listener), 0 === listeners.size && this.listeners.delete(sheet));
|
|
123
|
+
}
|
|
124
|
+
emitDataChange(event) {
|
|
125
|
+
const listeners = this.listeners.get(event.sheet);
|
|
126
|
+
if (listeners) for (const listener of listeners) try {
|
|
127
|
+
listener(event);
|
|
128
|
+
} catch (error) {}
|
|
129
|
+
const globalListeners = this.listeners.get("*");
|
|
130
|
+
if (globalListeners) for (const listener of globalListeners) try {
|
|
131
|
+
listener(event);
|
|
132
|
+
} catch (error) {}
|
|
133
|
+
}
|
|
134
|
+
forceSync() {
|
|
135
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
136
|
+
this.syncTimer && (clearTimeout(this.syncTimer), this.syncTimer = null), yield this.processChanges();
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
clearSyncQueue() {
|
|
140
|
+
this.changeQueue = [], this.syncTimer && (clearTimeout(this.syncTimer), this.syncTimer = null);
|
|
141
|
+
}
|
|
142
|
+
getSyncStatus() {
|
|
143
|
+
var _a;
|
|
144
|
+
return {
|
|
145
|
+
pendingChanges: this.changeQueue.length,
|
|
146
|
+
isSyncing: this.isSyncing,
|
|
147
|
+
lastSyncTime: this.changeQueue.length > 0 && (null === (_a = this.changeQueue[this.changeQueue.length - 1]) || void 0 === _a ? void 0 : _a.timestamp) || null
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
updateSyncOptions(options) {
|
|
151
|
+
this.options = Object.assign(Object.assign({}, this.options), options);
|
|
152
|
+
}
|
|
153
|
+
destroy() {
|
|
154
|
+
this.clearSyncQueue(), this.listeners.clear(), this.crossSheetManager.clearCache();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
exports.CrossSheetDataSynchronizer = CrossSheetDataSynchronizer;
|
|
159
|
+
//# sourceMappingURL=cross-sheet-data-synchronizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/formula/cross-sheet-data-synchronizer.ts"],"names":[],"mappings":"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","file":"cross-sheet-data-synchronizer.js","sourcesContent":["/**\n * 跨sheet数据同步器\n * 处理不同sheet之间的数据同步和更新通知\n */\n\nimport type { FormulaCell } from '../ts-types/formula';\nimport type { FormulaEngine } from './formula-engine';\nimport type { CrossSheetFormulaManager } from './cross-sheet-formula-manager';\n\nexport interface DataChangeEvent {\n sheet: string;\n cells: FormulaCell[];\n oldValues: any[];\n newValues: any[];\n timestamp: number;\n}\n\nexport interface SyncOptions {\n immediate: boolean;\n batchSize: number;\n timeout: number;\n}\n\nexport class CrossSheetDataSynchronizer {\n private formulaEngine: FormulaEngine;\n private crossSheetManager: CrossSheetFormulaManager;\n\n // 数据变更队列\n private changeQueue: DataChangeEvent[] = [];\n\n // 同步状态\n private isSyncing = false;\n private syncTimer: NodeJS.Timeout | null = null;\n\n // 同步选项\n private options: SyncOptions = {\n immediate: false,\n batchSize: 100,\n timeout: 50 // 50ms批处理\n };\n\n // 事件监听器\n private listeners: Map<string, Set<(event: DataChangeEvent) => void>> = new Map();\n\n constructor(formulaEngine: FormulaEngine, crossSheetManager: CrossSheetFormulaManager) {\n this.formulaEngine = formulaEngine;\n this.crossSheetManager = crossSheetManager;\n }\n\n /**\n * 注册数据变更\n */\n registerDataChange(sheet: string, cells: FormulaCell[], oldValues: any[], newValues: any[]): void {\n const event: DataChangeEvent = {\n sheet,\n cells,\n oldValues,\n newValues,\n timestamp: Date.now()\n };\n\n this.changeQueue.push(event);\n\n if (this.options.immediate) {\n this.processChanges();\n } else {\n this.scheduleSync();\n }\n }\n\n /**\n * 调度同步\n */\n private scheduleSync(): void {\n if (this.syncTimer) {\n clearTimeout(this.syncTimer);\n }\n\n this.syncTimer = setTimeout(() => {\n this.processChanges();\n }, this.options.timeout);\n }\n\n /**\n * 处理数据变更\n */\n private async processChanges(): Promise<void> {\n if (this.isSyncing || this.changeQueue.length === 0) {\n return;\n }\n\n this.isSyncing = true;\n\n try {\n // 批量处理变更\n const batch = this.changeQueue.splice(0, this.options.batchSize);\n\n // 按sheet分组处理\n const changesBySheet = this.groupChangesBySheet(batch);\n\n for (const [targetSheet, changes] of changesBySheet.entries()) {\n await this.syncSheetChanges(targetSheet, changes);\n }\n\n // 触发事件\n for (const event of batch) {\n this.emitDataChange(event);\n }\n } catch (error) {\n console.error('Error processing cross-sheet data changes:', error);\n } finally {\n this.isSyncing = false;\n\n // 如果还有剩余的变更,继续处理\n if (this.changeQueue.length > 0) {\n this.scheduleSync();\n }\n }\n }\n\n /**\n * 按sheet分组变更\n */\n private groupChangesBySheet(events: DataChangeEvent[]): Map<string, DataChangeEvent[]> {\n const groups = new Map<string, DataChangeEvent[]>();\n\n for (const event of events) {\n const existing = groups.get(event.sheet) || [];\n existing.push(event);\n groups.set(event.sheet, existing);\n }\n\n return groups;\n }\n\n /**\n * 同步指定sheet的变更\n */\n private async syncSheetChanges(targetSheet: string, changes: DataChangeEvent[]): Promise<void> {\n // 收集所有变化的单元格\n const allChangedCells: FormulaCell[] = [];\n const allOldValues: any[] = [];\n const allNewValues: any[] = [];\n\n for (const change of changes) {\n allChangedCells.push(...change.cells);\n allOldValues.push(...change.oldValues);\n allNewValues.push(...change.newValues);\n }\n\n // 使用跨sheet管理器更新引用\n await this.crossSheetManager.updateCrossSheetReferences(targetSheet, allChangedCells);\n }\n\n /**\n * 获取跨sheet依赖关系\n */\n getCrossSheetDependencies(): Map<string, string[]> {\n const dependencies = new Map<string, string[]>();\n\n const allSheets = this.formulaEngine.getAllSheets();\n for (const sheetInfo of allSheets) {\n const deps = this.crossSheetManager.getCrossSheetDependencies(sheetInfo.key);\n const targetSheets = deps.map(dep => dep.precedentSheet);\n dependencies.set(sheetInfo.key, targetSheets);\n }\n\n return dependencies;\n }\n\n /**\n * 验证跨sheet引用的完整性\n */\n validateCrossSheetReferences(): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n const allSheets = this.formulaEngine.getAllSheets();\n\n for (const sheetInfo of allSheets) {\n const validation = this.crossSheetManager.validateCrossSheetReferences(sheetInfo.key);\n if (!validation.valid) {\n errors.push(...validation.errors);\n }\n\n // 检查循环依赖\n const circularDeps = this.detectCircularDependencies(sheetInfo.key, new Set());\n if (circularDeps.length > 0) {\n errors.push(`Circular dependency detected in sheet ${sheetInfo.key}: ${circularDeps.join(' -> ')}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors\n };\n }\n\n /**\n * 检测循环依赖\n */\n private detectCircularDependencies(sheet: string, visited: Set<string>): string[] {\n if (visited.has(sheet)) {\n return [sheet];\n }\n\n visited.add(sheet);\n const dependencies = this.crossSheetManager.getCrossSheetDependencies(sheet);\n\n for (const dep of dependencies) {\n const cycle = this.detectCircularDependencies(dep.precedentSheet, new Set(visited));\n if (cycle.length > 0) {\n return [sheet, ...cycle];\n }\n }\n\n return [];\n }\n\n /**\n * 添加数据变更监听器\n */\n addDataChangeListener(sheet: string, listener: (event: DataChangeEvent) => void): void {\n if (!this.listeners.has(sheet)) {\n this.listeners.set(sheet, new Set());\n }\n this.listeners.get(sheet)!.add(listener);\n }\n\n /**\n * 移除数据变更监听器\n */\n removeDataChangeListener(sheet: string, listener: (event: DataChangeEvent) => void): void {\n const listeners = this.listeners.get(sheet);\n if (listeners) {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.listeners.delete(sheet);\n }\n }\n }\n\n /**\n * 触发数据变更事件\n */\n private emitDataChange(event: DataChangeEvent): void {\n const listeners = this.listeners.get(event.sheet);\n if (listeners) {\n for (const listener of listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Error in data change listener:', error);\n }\n }\n }\n\n // 也触发全局监听器\n const globalListeners = this.listeners.get('*');\n if (globalListeners) {\n for (const listener of globalListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Error in global data change listener:', error);\n }\n }\n }\n }\n\n /**\n * 强制立即同步\n */\n async forceSync(): Promise<void> {\n if (this.syncTimer) {\n clearTimeout(this.syncTimer);\n this.syncTimer = null;\n }\n\n await this.processChanges();\n }\n\n /**\n * 清除同步队列\n */\n clearSyncQueue(): void {\n this.changeQueue = [];\n if (this.syncTimer) {\n clearTimeout(this.syncTimer);\n this.syncTimer = null;\n }\n }\n\n /**\n * 获取同步状态\n */\n getSyncStatus(): {\n pendingChanges: number;\n isSyncing: boolean;\n lastSyncTime: number | null;\n } {\n return {\n pendingChanges: this.changeQueue.length,\n isSyncing: this.isSyncing,\n lastSyncTime:\n this.changeQueue.length > 0 ? this.changeQueue[this.changeQueue.length - 1]?.timestamp || null : null\n };\n }\n\n /**\n * 更新同步选项\n */\n updateSyncOptions(options: Partial<SyncOptions>): void {\n this.options = { ...this.options, ...options };\n }\n\n /**\n * 销毁同步器\n */\n destroy(): void {\n this.clearSyncQueue();\n this.listeners.clear();\n this.crossSheetManager.clearCache();\n }\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { FormulaCell } from '../ts-types/formula';
|
|
2
|
+
import type { FormulaEngine } from './formula-engine';
|
|
3
|
+
import { type ValidationResult } from './cross-sheet-formula-validator';
|
|
4
|
+
export interface CrossSheetFormulaOptions {
|
|
5
|
+
enableCaching: boolean;
|
|
6
|
+
enableValidation: boolean;
|
|
7
|
+
syncTimeout: number;
|
|
8
|
+
maxRecursionDepth: number;
|
|
9
|
+
}
|
|
10
|
+
export interface FormulaCalculationResult {
|
|
11
|
+
value: any;
|
|
12
|
+
error?: string;
|
|
13
|
+
dependencies: FormulaCell[];
|
|
14
|
+
calculationTime: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class CrossSheetFormulaHandler {
|
|
17
|
+
private formulaEngine;
|
|
18
|
+
private crossSheetManager;
|
|
19
|
+
private dataSynchronizer;
|
|
20
|
+
private validator;
|
|
21
|
+
private formulaManager?;
|
|
22
|
+
private options;
|
|
23
|
+
private isCalculating;
|
|
24
|
+
private calculationQueue;
|
|
25
|
+
private calculationResults;
|
|
26
|
+
constructor(formulaEngine: FormulaEngine, sheetManager?: {
|
|
27
|
+
getAllSheets: () => Array<{
|
|
28
|
+
sheetKey: string;
|
|
29
|
+
sheetTitle: string;
|
|
30
|
+
}>;
|
|
31
|
+
}, formulaManager?: any);
|
|
32
|
+
setCrossSheetFormula(cell: FormulaCell, formula: string): Promise<FormulaCalculationResult>;
|
|
33
|
+
getCrossSheetValue(cell: FormulaCell): Promise<FormulaCalculationResult>;
|
|
34
|
+
updateCrossSheetReferences(targetSheet: string, changedCells: FormulaCell[]): Promise<void>;
|
|
35
|
+
validateCrossSheetFormula(cell: FormulaCell): ValidationResult;
|
|
36
|
+
validateAllCrossSheetFormulas(): Map<string, ValidationResult>;
|
|
37
|
+
getCrossSheetDependencies(): Map<string, string[]>;
|
|
38
|
+
recalculateAllCrossSheetFormulas(): Promise<void>;
|
|
39
|
+
recalculateFormula(cell: FormulaCell): Promise<FormulaCalculationResult>;
|
|
40
|
+
private hasCrossSheetReference;
|
|
41
|
+
private cacheCalculationResult;
|
|
42
|
+
private getCachedResult;
|
|
43
|
+
private getCacheKey;
|
|
44
|
+
private parseA1Notation;
|
|
45
|
+
private getA1Notation;
|
|
46
|
+
updateOptions(options: Partial<CrossSheetFormulaOptions>): void;
|
|
47
|
+
getHandlerStatus(): {
|
|
48
|
+
isCalculating: boolean;
|
|
49
|
+
pendingCalculations: number;
|
|
50
|
+
cacheSize: number;
|
|
51
|
+
options: CrossSheetFormulaOptions;
|
|
52
|
+
};
|
|
53
|
+
clearCache(): void;
|
|
54
|
+
addDataChangeListener(sheet: string, listener: (event: any) => void): void;
|
|
55
|
+
removeDataChangeListener(sheet: string, listener: (event: any) => void): void;
|
|
56
|
+
forceSync(): Promise<void>;
|
|
57
|
+
destroy(): void;
|
|
58
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __awaiter = this && this.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
4
|
+
return new (P || (P = Promise))((function(resolve, reject) {
|
|
5
|
+
function fulfilled(value) {
|
|
6
|
+
try {
|
|
7
|
+
step(generator.next(value));
|
|
8
|
+
} catch (e) {
|
|
9
|
+
reject(e);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function rejected(value) {
|
|
13
|
+
try {
|
|
14
|
+
step(generator.throw(value));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function step(result) {
|
|
20
|
+
var value;
|
|
21
|
+
result.done ? resolve(result.value) : (value = result.value, value instanceof P ? value : new P((function(resolve) {
|
|
22
|
+
resolve(value);
|
|
23
|
+
}))).then(fulfilled, rejected);
|
|
24
|
+
}
|
|
25
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
Object.defineProperty(exports, "__esModule", {
|
|
30
|
+
value: !0
|
|
31
|
+
}), exports.CrossSheetFormulaHandler = void 0;
|
|
32
|
+
|
|
33
|
+
const cross_sheet_formula_manager_1 = require("./cross-sheet-formula-manager"), cross_sheet_data_synchronizer_1 = require("./cross-sheet-data-synchronizer"), cross_sheet_formula_validator_1 = require("./cross-sheet-formula-validator");
|
|
34
|
+
|
|
35
|
+
class CrossSheetFormulaHandler {
|
|
36
|
+
constructor(formulaEngine, sheetManager, formulaManager) {
|
|
37
|
+
this.options = {
|
|
38
|
+
enableCaching: !0,
|
|
39
|
+
enableValidation: !0,
|
|
40
|
+
syncTimeout: 50,
|
|
41
|
+
maxRecursionDepth: 100
|
|
42
|
+
}, this.isCalculating = !1, this.calculationQueue = [], this.calculationResults = new Map,
|
|
43
|
+
this.formulaEngine = formulaEngine, this.formulaManager = formulaManager, this.crossSheetManager = new cross_sheet_formula_manager_1.CrossSheetFormulaManager(formulaEngine, sheetManager),
|
|
44
|
+
this.dataSynchronizer = new cross_sheet_data_synchronizer_1.CrossSheetDataSynchronizer(formulaEngine, this.crossSheetManager),
|
|
45
|
+
this.validator = new cross_sheet_formula_validator_1.CrossSheetFormulaValidator(formulaEngine, this.crossSheetManager, sheetManager);
|
|
46
|
+
}
|
|
47
|
+
setCrossSheetFormula(cell, formula) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
49
|
+
const startTime = performance.now();
|
|
50
|
+
try {
|
|
51
|
+
if (this.options.enableValidation) {
|
|
52
|
+
const validation = this.validator.validateFormulaSyntax(formula);
|
|
53
|
+
if (!validation.valid) return {
|
|
54
|
+
value: null,
|
|
55
|
+
error: validation.error,
|
|
56
|
+
dependencies: [],
|
|
57
|
+
calculationTime: performance.now() - startTime
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
let result;
|
|
61
|
+
this.crossSheetManager.registerCrossSheetReference(formula, cell), this.formulaEngine.setCellContent(cell, formula),
|
|
62
|
+
result = this.formulaManager ? this.formulaManager.getCellValue(cell) : this.formulaEngine.getCellValue(cell);
|
|
63
|
+
const dependencies = this.formulaEngine.getCellPrecedents(cell), calculationResult = {
|
|
64
|
+
value: result.value,
|
|
65
|
+
error: result.error,
|
|
66
|
+
dependencies: dependencies,
|
|
67
|
+
calculationTime: performance.now() - startTime
|
|
68
|
+
};
|
|
69
|
+
return this.options.enableCaching && this.cacheCalculationResult(cell, calculationResult),
|
|
70
|
+
calculationResult;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return {
|
|
73
|
+
value: null,
|
|
74
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
75
|
+
dependencies: [],
|
|
76
|
+
calculationTime: performance.now() - startTime
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
getCrossSheetValue(cell) {
|
|
82
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
83
|
+
const startTime = performance.now();
|
|
84
|
+
try {
|
|
85
|
+
if (this.options.enableCaching) {
|
|
86
|
+
const cached = this.getCachedResult(cell);
|
|
87
|
+
if (cached) return Object.assign(Object.assign({}, cached), {
|
|
88
|
+
calculationTime: performance.now() - startTime
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (!this.formulaEngine.getCellFormula(cell)) return {
|
|
92
|
+
value: null,
|
|
93
|
+
error: "No formula found",
|
|
94
|
+
dependencies: [],
|
|
95
|
+
calculationTime: performance.now() - startTime
|
|
96
|
+
};
|
|
97
|
+
let result;
|
|
98
|
+
result = this.formulaManager ? this.formulaManager.getCellValue(cell) : this.formulaEngine.getCellValue(cell);
|
|
99
|
+
const dependencies = this.formulaEngine.getCellPrecedents(cell), calculationResult = {
|
|
100
|
+
value: result.value,
|
|
101
|
+
error: result.error,
|
|
102
|
+
dependencies: dependencies,
|
|
103
|
+
calculationTime: performance.now() - startTime
|
|
104
|
+
};
|
|
105
|
+
return this.options.enableCaching && this.cacheCalculationResult(cell, calculationResult),
|
|
106
|
+
calculationResult;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
value: null,
|
|
110
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
111
|
+
dependencies: [],
|
|
112
|
+
calculationTime: performance.now() - startTime
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
updateCrossSheetReferences(targetSheet, changedCells) {
|
|
118
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
119
|
+
yield this.crossSheetManager.updateCrossSheetReferences(targetSheet, changedCells);
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
validateCrossSheetFormula(cell) {
|
|
123
|
+
const formula = this.formulaEngine.getCellFormula(cell);
|
|
124
|
+
if (!formula) return {
|
|
125
|
+
valid: !1,
|
|
126
|
+
errors: [ {
|
|
127
|
+
type: "MISSING_REFERENCE",
|
|
128
|
+
message: "No formula found",
|
|
129
|
+
sheet: cell.sheet,
|
|
130
|
+
cell: cell
|
|
131
|
+
} ],
|
|
132
|
+
warnings: []
|
|
133
|
+
};
|
|
134
|
+
const syntaxValidation = this.validator.validateFormulaSyntax(formula);
|
|
135
|
+
return {
|
|
136
|
+
valid: syntaxValidation.valid,
|
|
137
|
+
errors: syntaxValidation.error ? [ {
|
|
138
|
+
type: "MISSING_REFERENCE",
|
|
139
|
+
message: syntaxValidation.error,
|
|
140
|
+
sheet: cell.sheet,
|
|
141
|
+
cell: cell
|
|
142
|
+
} ] : [],
|
|
143
|
+
warnings: []
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
validateAllCrossSheetFormulas() {
|
|
147
|
+
return this.validator.validateAllSheets();
|
|
148
|
+
}
|
|
149
|
+
getCrossSheetDependencies() {
|
|
150
|
+
return this.dataSynchronizer.getCrossSheetDependencies();
|
|
151
|
+
}
|
|
152
|
+
recalculateAllCrossSheetFormulas() {
|
|
153
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
154
|
+
const allSheets = this.formulaEngine.getAllSheets();
|
|
155
|
+
for (const sheetInfo of allSheets) {
|
|
156
|
+
const formulas = this.formulaEngine.exportFormulas(sheetInfo.key);
|
|
157
|
+
for (const [cellRef, formula] of Object.entries(formulas)) if (this.hasCrossSheetReference(formula)) {
|
|
158
|
+
const cell = this.parseA1Notation(cellRef), cellWithSheet = {
|
|
159
|
+
sheet: sheetInfo.key,
|
|
160
|
+
row: cell.row,
|
|
161
|
+
col: cell.col
|
|
162
|
+
};
|
|
163
|
+
yield this.recalculateFormula(cellWithSheet);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
recalculateFormula(cell) {
|
|
169
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
170
|
+
return yield this.getCrossSheetValue(cell);
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
hasCrossSheetReference(formula) {
|
|
174
|
+
return formula.includes("!");
|
|
175
|
+
}
|
|
176
|
+
cacheCalculationResult(cell, result) {
|
|
177
|
+
const cacheKey = this.getCacheKey(cell);
|
|
178
|
+
this.calculationResults.set(cacheKey, result);
|
|
179
|
+
}
|
|
180
|
+
getCachedResult(cell) {
|
|
181
|
+
const cacheKey = this.getCacheKey(cell);
|
|
182
|
+
return this.calculationResults.get(cacheKey) || null;
|
|
183
|
+
}
|
|
184
|
+
getCacheKey(cell) {
|
|
185
|
+
return `${cell.sheet}!${this.getA1Notation(cell.row, cell.col)}`;
|
|
186
|
+
}
|
|
187
|
+
parseA1Notation(a1Notation) {
|
|
188
|
+
const match = a1Notation.match(/^([A-Z]+)([0-9]+)$/);
|
|
189
|
+
if (!match) throw new Error(`Invalid cell reference: ${a1Notation}`);
|
|
190
|
+
const colLetters = match[1], rowNumber = parseInt(match[2], 10);
|
|
191
|
+
let col = 0;
|
|
192
|
+
for (let i = 0; i < colLetters.length; i++) col = 26 * col + (colLetters.charCodeAt(i) - 65);
|
|
193
|
+
return {
|
|
194
|
+
row: rowNumber - 1,
|
|
195
|
+
col: col
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
getA1Notation(row, col) {
|
|
199
|
+
let colStr = "", tempCol = col;
|
|
200
|
+
do {
|
|
201
|
+
colStr = String.fromCharCode(65 + tempCol % 26) + colStr, tempCol = Math.floor(tempCol / 26) - 1;
|
|
202
|
+
} while (tempCol >= 0);
|
|
203
|
+
return `${colStr}${row + 1}`;
|
|
204
|
+
}
|
|
205
|
+
updateOptions(options) {
|
|
206
|
+
this.options = Object.assign(Object.assign({}, this.options), options), this.dataSynchronizer.updateSyncOptions({
|
|
207
|
+
immediate: this.options.enableCaching,
|
|
208
|
+
timeout: this.options.syncTimeout
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
getHandlerStatus() {
|
|
212
|
+
return {
|
|
213
|
+
isCalculating: this.isCalculating,
|
|
214
|
+
pendingCalculations: this.calculationQueue.length,
|
|
215
|
+
cacheSize: this.calculationResults.size,
|
|
216
|
+
options: Object.assign({}, this.options)
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
clearCache() {
|
|
220
|
+
this.calculationResults.clear(), this.crossSheetManager.clearCache(), this.validator.clearCache();
|
|
221
|
+
}
|
|
222
|
+
addDataChangeListener(sheet, listener) {
|
|
223
|
+
this.dataSynchronizer.addDataChangeListener(sheet, listener);
|
|
224
|
+
}
|
|
225
|
+
removeDataChangeListener(sheet, listener) {
|
|
226
|
+
this.dataSynchronizer.removeDataChangeListener(sheet, listener);
|
|
227
|
+
}
|
|
228
|
+
forceSync() {
|
|
229
|
+
return __awaiter(this, void 0, void 0, (function*() {
|
|
230
|
+
yield this.dataSynchronizer.forceSync();
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
destroy() {
|
|
234
|
+
this.clearCache(), this.calculationResults.clear(), this.calculationQueue = [],
|
|
235
|
+
this.crossSheetManager.destroy(), this.dataSynchronizer.destroy(), this.validator.destroy();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
exports.CrossSheetFormulaHandler = CrossSheetFormulaHandler;
|
|
240
|
+
//# sourceMappingURL=cross-sheet-formula-handler.js.map
|