Explorar o código

华创启德质量指标:修复百分比公式转换问题

ZhuJiaHao hai 1 semana
pai
achega
0ef3623e7a

+ 230 - 81
public/luckysheet.html

@@ -36,93 +36,242 @@
       return sheetData.map(sheet => {
         if (!sheet) return sheet
         
-        // 修复celldata中的公式
-        if (Array.isArray(sheet.celldata)) {
-          sheet.celldata.forEach(cell => {
-            if (cell && cell.v && cell.v.f) {
-              let formula = cell.v.f
-              let newFormula = formula
-              
-              // 将 _xleta.N 替换为 "N"
-              if (formula.includes('_xleta.')) {
-                newFormula = newFormula.replace(/_xleta\.([A-Za-z]+)/g, (match, variable) => {
-                  // 如果是单个字母,替换为字符串
-                  if (/^[A-Za-z]$/.test(variable)) {
-                    return `"${variable}"`
-                  }
-                  return variable
-                })
-              }
-              
-              // 修复百分比格式问题
-              // 将百分比转换为数值,因为Excel中100%就是数值1
-              const percentRegex = /(\d+)%/g
-              const percentMatches = [...newFormula.matchAll(percentRegex)]
-              
-              if (percentMatches.length > 0) {
-                percentMatches.forEach(match => {
-                  const fullMatch = match[0]
-                  const number = match[1]
-                  const percentValue = parseFloat(number) / 100
-                  
-                  // 将百分比转换为数值
-                  newFormula = newFormula.replace(fullMatch, percentValue.toString())
-                })
-              }
-              
-              if (newFormula !== formula) {
-                cell.v.f = newFormula
-              }
-            }
-          })
-        }
+        // 第一步:修复公式语法问题
+        sheet = fixFormulaSyntax(sheet)
+        
+        // 第二步:修复计算链问题
+        sheet = fixLuckysheetCalcChain(sheet)
         
-        // 修复data数组中的公式
-        if (Array.isArray(sheet.data)) {
-          sheet.data.forEach(row => {
-            if (Array.isArray(row)) {
-              row.forEach(cell => {
-                if (cell && cell.f) {
-                  let formula = cell.f
-                  let newFormula = formula
-                  
-                  // 将 _xleta.N 替换为 "N"
-                  if (formula.includes('_xleta.')) {
-                    newFormula = newFormula.replace(/_xleta\.([A-Za-z]+)/g, (match, variable) => {
-                      // 如果是单个字母,替换为字符串
-                      if (/^[A-Za-z]$/.test(variable)) {
-                        return `"${variable}"`
-                      }
-                      return variable
-                    })
-                  }
-                  
-                  // 修复百分比格式问题
-                  const percentRegex = /(\d+)%/g
-                  const percentMatches = [...newFormula.matchAll(percentRegex)]
-                  
-                  if (percentMatches.length > 0) {
-                    percentMatches.forEach(match => {
-                      const fullMatch = match[0]
-                      const number = match[1]
-                      const percentValue = parseFloat(number) / 100
-                      
-                      // 将百分比转换为数值
-                      newFormula = newFormula.replace(fullMatch, percentValue.toString())
-                    })
-                  }
-                  
-                  if (newFormula !== formula) {
-                    cell.f = newFormula
-                  }
+        return sheet
+      })
+    }
+    
+    // 修复公式语法问题(与导入模块相同的逻辑)
+    function fixFormulaSyntax(sheet) {
+      if (!sheet) return sheet
+      
+      // 修复celldata中的公式
+      if (Array.isArray(sheet.celldata)) {
+        sheet.celldata.forEach(cell => {
+          if (cell && cell.v && cell.v.f) {
+            let formula = cell.v.f
+            let newFormula = formula
+            
+            // 将 _xleta.N 替换为 "N"
+            if (formula.includes('_xleta.')) {
+              newFormula = newFormula.replace(/_xleta\.([A-Za-z]+)/g, (match, variable) => {
+                // 如果是单个字母,替换为字符串
+                if (/^[A-Za-z]$/.test(variable)) {
+                  return `"${variable}"`
+                }
+                return variable
+              })
+            }
+            
+            // 修复百分比格式问题
+            // 将百分比转换为数值,因为Excel中100%就是数值1,0.01%就是0.0001
+            // 支持整数和小数百分比,如 100%、0.01%、1.5%
+            
+            // 第一步:先修复可能存在的重复小数点问题(如0.0.01应该修正为0.0001)
+            const duplicateDotRegex = /(\d+)\.(\d+)\.(\d+)/g
+            const duplicateDotMatches = [...newFormula.matchAll(duplicateDotRegex)]
+            
+            if (duplicateDotMatches.length > 0) {
+              duplicateDotMatches.forEach(match => {
+                const fullMatch = match[0]
+                const integerPart = match[1]  // 如 "0"
+                const firstDecimalPart = match[2]  // 如 "0"
+                const secondDecimalPart = match[3]  // 如 "01"
+                
+                // 处理常见的百分比解析错误模式
+                let correctNumber
+                if (integerPart === '0' && firstDecimalPart === '0') {
+                  // 针对 0.0.xxx 模式的特殊修复
+                  // 规则:转换为 0.00xxx,其中 xxx 是 secondDecimalPart
+                  correctNumber = parseFloat(`0.00${secondDecimalPart}`)
+                } else {
+                  // 其他情况:使用更保守的修复
+                  correctNumber = parseFloat(`${integerPart}.${firstDecimalPart}${secondDecimalPart}`)
                 }
+                
+                newFormula = newFormula.replace(fullMatch, correctNumber.toString())
+              })
+            }
+            
+            // 第二步:处理百分比转换为数值的问题
+            const percentRegex = /(\d+(?:\.\d+)?)%/g
+            const percentMatches = [...newFormula.matchAll(percentRegex)]
+            
+            if (percentMatches.length > 0) {
+              percentMatches.forEach(match => {
+                const fullMatch = match[0]
+                const number = match[1]
+                const percentValue = parseFloat(number) / 100
+                
+                // 将百分比转换为数值
+                newFormula = newFormula.replace(fullMatch, percentValue.toString())
               })
             }
-          })
+            
+            if (newFormula !== formula) {
+              cell.v.f = newFormula
+            }
+          }
+        })
+      }
+      
+      // 修复data数组中的公式
+      if (Array.isArray(sheet.data)) {
+        sheet.data.forEach(row => {
+          if (Array.isArray(row)) {
+            row.forEach(cell => {
+              if (cell && cell.f) {
+                let formula = cell.f
+                let newFormula = formula
+                
+                // 将 _xleta.N 替换为 "N"
+                if (formula.includes('_xleta.')) {
+                  newFormula = newFormula.replace(/_xleta\.([A-Za-z]+)/g, (match, variable) => {
+                    // 如果是单个字母,替换为字符串
+                    if (/^[A-Za-z]$/.test(variable)) {
+                      return `"${variable}"`
+                    }
+                    return variable
+                  })
+                }
+                
+                // 修复百分比格式问题
+                // 支持整数和小数百分比,如 100%、0.01%、1.5%
+                
+                // 第一步:先修复可能存在的重复小数点问题(如0.0.01应该修正为0.0001)
+                const duplicateDotRegex = /(\d+)\.(\d+)\.(\d+)/g
+                const duplicateDotMatches = [...newFormula.matchAll(duplicateDotRegex)]
+                
+                if (duplicateDotMatches.length > 0) {
+                  duplicateDotMatches.forEach(match => {
+                    const fullMatch = match[0]
+                    const integerPart = match[1]  // 如 "0"
+                    const firstDecimalPart = match[2]  // 如 "0"
+                    const secondDecimalPart = match[3]  // 如 "01"
+                    
+                    // 处理常见的百分比解析错误模式
+                    let correctNumber
+                    if (integerPart === '0' && firstDecimalPart === '0') {
+                      // 针对 0.0.xxx 模式的特殊修复
+                      // 规则:转换为 0.00xxx,其中 xxx 是 secondDecimalPart
+                      correctNumber = parseFloat(`0.00${secondDecimalPart}`)
+                    } else {
+                      // 其他情况:使用更保守的修复
+                      correctNumber = parseFloat(`${integerPart}.${firstDecimalPart}${secondDecimalPart}`)
+                    }
+                    
+                    newFormula = newFormula.replace(fullMatch, correctNumber.toString())
+                  })
+                }
+                
+                // 第二步:处理百分比转换为数值的问题
+                const percentRegex = /(\d+(?:\.\d+)?)%/g
+                const percentMatches = [...newFormula.matchAll(percentRegex)]
+                
+                if (percentMatches.length > 0) {
+                  percentMatches.forEach(match => {
+                    const fullMatch = match[0]
+                    const number = match[1]
+                    const percentValue = parseFloat(number) / 100
+                    
+                    // 将百分比转换为数值
+                    newFormula = newFormula.replace(fullMatch, percentValue.toString())
+                  })
+                }
+                
+                if (newFormula !== formula) {
+                  cell.f = newFormula
+                }
+              }
+            })
+          }
+        })
+      }
+      
+      return sheet
+    }
+    
+    /**
+     * 修复luckysheet计算链问题
+     * 确保所有包含公式的单元格都能正常计算
+     * 这是解决"G11和H11公式工作,但I11及以后不工作"问题的关键
+     * 
+     * @param {Object} sheet - 工作表数据
+     * @returns {Object} 修复后的工作表
+     */
+    function fixLuckysheetCalcChain(sheet) {
+      if (!sheet) return sheet
+      
+      // 确保calcChain存在
+      if (!sheet.calcChain) {
+        sheet.calcChain = []
+      }
+      
+      // 创建现有计算链的快速查找映射
+      const existingCalcMap = new Map()
+      sheet.calcChain.forEach(item => {
+        if (item && typeof item.r === 'number' && typeof item.c === 'number') {
+          const key = `${item.r}_${item.c}`
+          existingCalcMap.set(key, true)
         }
-        
-        return sheet
       })
+      
+      /**
+       * 添加单元格到计算链
+       * @param {number} row - 行索引
+       * @param {number} col - 列索引
+       */
+      const addToCalcChain = (row, col) => {
+        const key = `${row}_${col}`
+        
+        // 如果已经存在,跳过
+        if (existingCalcMap.has(key)) {
+          return
+        }
+        
+        // 添加到计算链
+        sheet.calcChain.push({
+          r: row,
+          c: col,
+          index: sheet.index || "0"
+        })
+        
+        // 更新映射
+        existingCalcMap.set(key, true)
+      }
+      
+      // 遍历celldata,查找有公式的单元格
+      if (Array.isArray(sheet.celldata)) {
+        sheet.celldata.forEach(cell => {
+          if (cell && typeof cell.r === 'number' && typeof cell.c === 'number') {
+            // 检查是否有公式
+            const hasFormula = cell.v && cell.v.f
+            if (hasFormula) {
+              addToCalcChain(cell.r, cell.c)
+            }
+          }
+        })
+      }
+      
+      // 遍历data数组,查找有公式的单元格
+      if (Array.isArray(sheet.data)) {
+        sheet.data.forEach((row, rowIndex) => {
+          if (Array.isArray(row)) {
+            row.forEach((cell, colIndex) => {
+              if (cell && cell.f) {
+                addToCalcChain(rowIndex, colIndex)
+              }
+            })
+          }
+        })
+      }
+      
+      return sheet
     }
     
     window.addEventListener('message', function(event) {

+ 0 - 7
src/views/component/onlineSheet/onlineSheetData.vue

@@ -163,7 +163,6 @@ export default {
         // 注意:不再从后端加载数据,因为我们已将后端保存接口注释
         // 所有数据都直接来自父组件传递的 biaoGeNeiRong 字段
       } catch (e) {
-        console.error('解析表格数据失败:', e)
         this.sheetData = null
       }
     },
@@ -178,7 +177,6 @@ export default {
           }
         }
       } catch (error) {
-        console.error('加载表格数据失败:', error)
         this.$message.error('加载表格数据失败!')
       }
     },
@@ -246,7 +244,6 @@ export default {
             this.$message.error('导入失败:Excel 文件为空或格式错误!')
           }
         } catch (error) {
-          console.error('导入错误:', error)
           this.$message.error(`导入失败:${error.message || '文件解析错误,请检查文件格式是否正确'}`)
         } finally {
           loading.close()
@@ -256,7 +253,6 @@ export default {
           }
         }
       } catch (outerError) {
-        console.error('导入外层错误:', outerError)
         this.$message.error('导入过程发生异常')
       }
     },
@@ -293,7 +289,6 @@ export default {
           this.$message.warning('没有表格数据可保存!')
         }
       } catch (error) {
-        console.error('保存错误:', error)
         this.$message.error(`保存失败:${error.message || '数据处理错误'}`)
       }
     },
@@ -312,14 +307,12 @@ export default {
           // 使用外部导出模块
           await this.useExternalExport(loading)
         } catch (error) {
-          console.error('导出错误:', error)
           this.$message.error(`导出失败: ${error.message || '数据处理错误'}`)
         } finally {
           loading.close()
         }
         
       } catch (outerError) {
-        console.error('导出外层错误:', outerError)
         this.$message.error('导出过程发生异常')
       }
     },

+ 0 - 1
src/views/component/onlineSheet/onlineSheetExcelExport.js

@@ -397,7 +397,6 @@ export async function exportToExcel(sheetData, fileName = null) {
     return { success: true, fileName: finalFileName }
     
   } catch (error) {
-    console.error('Excel导出错误:', error)
     return { success: false, error: error.message }
   }
 }

+ 272 - 89
src/views/component/onlineSheet/onlineSheetExcelImport.js

@@ -3,8 +3,12 @@ import * as XLSX from 'xlsx'
 
 /**
  * 修复luckysheet中的公式解析问题
- * 主要解决:Excel公式 =IF(E6=100%,"Y",N) 被luckyexcel解析为 =IF(E6=100%,"Y",_xleta.N) 的问题
- * 同时修复百分比格式和公式语法问题
+ * 主要解决以下问题:
+ * 1. Excel公式 =IF(E6=100%,"Y",N) 被luckyexcel解析为 =IF(E6=100%,"Y",_xleta.N) 的问题
+ * 2. 百分比格式问题:将100%转换为数值1
+ * 3. 计算链缺失问题:确保所有包含公式的单元格都被正确添加到calcChain中
+ * 4. 通用公式语法修复
+ * 
  * @param {Array} sheetData - luckysheet数据
  * @returns {Array} 修复后的数据
  */
@@ -16,18 +20,150 @@ export function fixLuckySheetFormulas(sheetData) {
     return sheetData.map(sheet => {
       if (!sheet) return sheet
       
-      // 修复celldata中的公式
-      if (Array.isArray(sheet.celldata)) {
-        sheet.celldata.forEach(cell => {
-          if (cell && cell.v && cell.v.f) {
-            const formula = cell.v.f
-            let newFormula = formula
+      // 第一步:修复公式语法问题(百分比格式、_xleta前缀等)
+      sheet = fixFormulaSyntax(sheet)
+      
+      // 第二步:修复计算链,确保所有公式单元格都能正常计算
+      sheet = fixCalcChain(sheet)
+      
+      return sheet
+    })
+  } catch (error) {
+    return sheetData
+  }
+}
+
+/**
+ * 修复公式语法问题
+ * 包括:_xleta前缀修复、百分比格式转换等
+ * 
+ * @param {Object} sheet - 单个工作表数据
+ * @returns {Object} 修复后的工作表
+ */
+function fixFormulaSyntax(sheet) {
+  if (!sheet) return sheet
+  
+  // 修复celldata中的公式
+  if (Array.isArray(sheet.celldata)) {
+    sheet.celldata.forEach(cell => {
+      if (cell && cell.v && cell.v.f) {
+        const formula = cell.v.f
+        let newFormula = formula
+        
+        // 修复 _xleta.N 问题
+        // 检查公式模式: =IF(E6=100%,"Y",_xleta.N)
+        // 修复为: =IF(E6=100%,"Y","N")
+        
+        // 更精确的匹配:只匹配在函数参数位置且不在函数名位置的_xleta.N
+        const regex = /(IF\([^,]+,[^,]+,)_xleta\.(N)(\))/g
+        const matches = [...formula.matchAll(regex)]
+        
+        if (matches.length > 0) {
+          matches.forEach(match => {
+            const before = match[1]
+            const variable = match[2]
+            const after = match[3]
+            
+            // 对于字母N、Y等,作为字符串处理
+            const isSimpleLetter = /^[A-Za-z]$/.test(variable)
+            if (isSimpleLetter) {
+              // 对于简单字母变量,替换为字符串
+              const replacement = `${before}"${variable}"${after}`
+              newFormula = newFormula.replace(match[0], replacement)
+            }
+          })
+        }
+        
+        // 更通用的修复:处理其他_xleta前缀的变量
+        // 例如: _xleta.Y, _xleta.VAR 等
+        const genericRegex = /_xleta\.([A-Za-z]+)/g
+        const genericMatches = [...newFormula.matchAll(genericRegex)]
+        
+        if (genericMatches.length > 0) {
+          genericMatches.forEach(match => {
+            const fullMatch = match[0]
+            const variableName = match[1]
+            
+            // 判断是否为简单变量名(单个字母)
+            if (/^[A-Za-z]$/.test(variableName)) {
+              newFormula = newFormula.replace(fullMatch, `"${variableName}"`)
+            }
+          })
+        }
+        
+        // 智能修复百分比格式问题
+        // 对于公式 =IF(E6=100%,"Y","N"),需要将100%转换为luckysheet能理解的格式
+        // 同时需要处理小数百分比,如 =IF(E15<=0.01%,"Y","N"),应该转换为 =IF(E15<=0.0001,"Y","N")
+        
+        // 第一步:先修复可能存在的重复小数点问题(如0.0.01应该修正为0.0001)
+        // 这种问题可能发生在luckyexcel解析过程中
+        // 问题:0.01% 被错误解析为 0.0.01,实际上应该是 0.0001
+        const duplicateDotRegex = /(\d+)\.(\d+)\.(\d+)/g
+        const duplicateDotMatches = [...newFormula.matchAll(duplicateDotRegex)]
+        
+        if (duplicateDotMatches.length > 0) {
+          duplicateDotMatches.forEach(match => {
+            const fullMatch = match[0]
+            const integerPart = match[1]  // 如 "0"
+            const firstDecimalPart = match[2]  // 如 "0"
+            const secondDecimalPart = match[3]  // 如 "01"
+            
+            // 处理常见的百分比解析错误模式
+            // 1. 0.01% 被解析为 0.0.01,应该修正为 0.0001
+            // 2. 0.1% 被解析为 0.0.1,应该修正为 0.001
+            // 3. 0.001% 被解析为 0.0.001,应该修正为 0.00001
+            // 经过分析发现规律:0.0.xxx 模式通常表示 xxx/100 的百分比
+            // 例如:0.0.01 表示 0.01% = 0.0001,0.0.1 表示 0.1% = 0.001
             
-            // 修复 _xleta.N 问题
-            // 检查公式模式: =IF(E6=100%,"Y",_xleta.N)
-            // 修复为: =IF(E6=100%,"Y","N")
+            let correctNumber
+            if (integerPart === '0' && firstDecimalPart === '0') {
+              // 针对 0.0.xxx 模式的特殊修复
+              // 规则:转换为 0.00xxx,其中 xxx 是 secondDecimalPart
+              // 例如:0.0.01 → 0.0001,0.0.1 → 0.001,0.0.001 → 0.00001
+              correctNumber = parseFloat(`0.00${secondDecimalPart}`)
+            } else {
+              // 其他情况:使用更保守的修复
+              // 将 X.Y.Z 合并为 X.YZ(假设第一个小数部分是整数部分的小数)
+              correctNumber = parseFloat(`${integerPart}.${firstDecimalPart}${secondDecimalPart}`)
+            }
+            
+            newFormula = newFormula.replace(fullMatch, correctNumber.toString())
+          })
+        }
+        
+        // 第二步:处理百分比转换为数值的问题
+        // 支持整数和小数百分比,如 100%、0.01%、1.5%
+        const percentRegex = /(\d+(?:\.\d+)?)%/g
+        const percentMatches = [...newFormula.matchAll(percentRegex)]
+        
+        if (percentMatches.length > 0) {
+          percentMatches.forEach(match => {
+            const fullMatch = match[0]
+            const number = match[1]
+            const percentValue = parseFloat(number) / 100
+            
+            // 将百分比转换为数值,因为Excel中100%就是数值1,0.01%就是0.0001
+            newFormula = newFormula.replace(fullMatch, percentValue.toString())
+          })
+        }
+        
+        if (newFormula !== formula) {
+          cell.v.f = newFormula
+        }
+      }
+    })
+  }
+  
+  // 修复data数组中的公式
+  if (Array.isArray(sheet.data)) {
+    sheet.data.forEach((row, rowIndex) => {
+      if (Array.isArray(row)) {
+        row.forEach((cell, colIndex) => {
+          if (cell && cell.f) {
+            const formula = cell.f
+            let newFormula = formula
             
-            // 更精确的匹配:只匹配在函数参数位置且不在函数名位置的_xleta.N
+            // 修复 _xleta.N 问题(与上面相同的逻辑)
             const regex = /(IF\([^,]+,[^,]+,)_xleta\.(N)(\))/g
             const matches = [...formula.matchAll(regex)]
             
@@ -37,18 +173,15 @@ export function fixLuckySheetFormulas(sheetData) {
                 const variable = match[2]
                 const after = match[3]
                 
-                // 对于字母N、Y等,作为字符串处理
                 const isSimpleLetter = /^[A-Za-z]$/.test(variable)
                 if (isSimpleLetter) {
-                  // 对于简单字母变量,替换为字符串
                   const replacement = `${before}"${variable}"${after}`
                   newFormula = newFormula.replace(match[0], replacement)
                 }
               })
             }
             
-            // 更通用的修复:处理其他_xleta前缀的变量
-            // 例如: _xleta.Y, _xleta.VAR 等
+            // 通用修复
             const genericRegex = /_xleta\.([A-Za-z]+)/g
             const genericMatches = [...newFormula.matchAll(genericRegex)]
             
@@ -57,7 +190,6 @@ export function fixLuckySheetFormulas(sheetData) {
                 const fullMatch = match[0]
                 const variableName = match[1]
                 
-                // 判断是否为简单变量名(单个字母)
                 if (/^[A-Za-z]$/.test(variableName)) {
                   newFormula = newFormula.replace(fullMatch, `"${variableName}"`)
                 }
@@ -65,8 +197,36 @@ export function fixLuckySheetFormulas(sheetData) {
             }
             
             // 智能修复百分比格式问题
-            // 对于公式 =IF(E6=100%,"Y","N"),需要将100%转换为luckysheet能理解的格式
-            const percentRegex = /(\d+)%/g
+            // 处理整数和小数百分比,如 100% 转换为 1,0.01% 转换为 0.0001
+            
+            // 第一步:先修复可能存在的重复小数点问题(如0.0.01应该修正为0.0001)
+            const duplicateDotRegex = /(\d+)\.(\d+)\.(\d+)/g
+            const duplicateDotMatches = [...newFormula.matchAll(duplicateDotRegex)]
+            
+            if (duplicateDotMatches.length > 0) {
+              duplicateDotMatches.forEach(match => {
+                const fullMatch = match[0]
+                const integerPart = match[1]  // 如 "0"
+                const firstDecimalPart = match[2]  // 如 "0"
+                const secondDecimalPart = match[3]  // 如 "01"
+                
+                // 处理常见的百分比解析错误模式
+                let correctNumber
+                if (integerPart === '0' && firstDecimalPart === '0') {
+                  // 针对 0.0.xxx 模式的特殊修复
+                  // 规则:转换为 0.00xxx,其中 xxx 是 secondDecimalPart
+                  correctNumber = parseFloat(`0.00${secondDecimalPart}`)
+                } else {
+                  // 其他情况:使用更保守的修复
+                  correctNumber = parseFloat(`${integerPart}.${firstDecimalPart}${secondDecimalPart}`)
+                }
+                
+                newFormula = newFormula.replace(fullMatch, correctNumber.toString())
+              })
+            }
+            
+            // 第二步:处理百分比转换为数值的问题
+            const percentRegex = /(\d+(?:\.\d+)?)%/g
             const percentMatches = [...newFormula.matchAll(percentRegex)]
             
             if (percentMatches.length > 0) {
@@ -75,90 +235,113 @@ export function fixLuckySheetFormulas(sheetData) {
                 const number = match[1]
                 const percentValue = parseFloat(number) / 100
                 
-                // 将百分比转换为数值,因为Excel中100%就是数值1
-                // 这是最可能工作的方案
+                // 将百分比转换为数值
                 newFormula = newFormula.replace(fullMatch, percentValue.toString())
               })
             }
             
             if (newFormula !== formula) {
-              cell.v.f = newFormula
+              cell.f = newFormula
             }
           }
         })
       }
-      
-      // 修复data数组中的公式
-      if (Array.isArray(sheet.data)) {
-        sheet.data.forEach((row, rowIndex) => {
-          if (Array.isArray(row)) {
-            row.forEach((cell, colIndex) => {
-              if (cell && cell.f) {
-                const formula = cell.f
-                let newFormula = formula
-                
-                // 修复 _xleta.N 问题(与上面相同的逻辑)
-                const regex = /(IF\([^,]+,[^,]+,)_xleta\.(N)(\))/g
-                const matches = [...formula.matchAll(regex)]
-                
-                if (matches.length > 0) {
-                  matches.forEach(match => {
-                    const before = match[1]
-                    const variable = match[2]
-                    const after = match[3]
-                    
-                    const isSimpleLetter = /^[A-Za-z]$/.test(variable)
-                    if (isSimpleLetter) {
-                      const replacement = `${before}"${variable}"${after}`
-                      newFormula = newFormula.replace(match[0], replacement)
-                    }
-                  })
-                }
-                
-                // 通用修复
-                const genericRegex = /_xleta\.([A-Za-z]+)/g
-                const genericMatches = [...newFormula.matchAll(genericRegex)]
-                
-                if (genericMatches.length > 0) {
-                  genericMatches.forEach(match => {
-                    const fullMatch = match[0]
-                    const variableName = match[1]
-                    
-                    if (/^[A-Za-z]$/.test(variableName)) {
-                      newFormula = newFormula.replace(fullMatch, `"${variableName}"`)
-                    }
-                  })
-                }
-                
-                // 智能修复百分比格式问题
-                const percentRegex = /(\d+)%/g
-                const percentMatches = [...newFormula.matchAll(percentRegex)]
-                
-                if (percentMatches.length > 0) {
-                  percentMatches.forEach(match => {
-                    const fullMatch = match[0]
-                    const number = match[1]
-                    const percentValue = parseFloat(number) / 100
-                    
-                    // 将百分比转换为数值
-                    newFormula = newFormula.replace(fullMatch, percentValue.toString())
-                  })
-                }
-                
-                if (newFormula !== formula) {
-                  cell.f = newFormula
-                }
-              }
-            })
+    })
+  }
+  
+  return sheet
+}
+
+/**
+ * 修复计算链(calcChain)
+ * 问题描述:某些包含公式的单元格没有被正确添加到calcChain中,导致公式不计算
+ * 例如:G11和H11公式工作,但I11及以后的公式不工作
+ * 
+ * 解决方案:
+ * 1. 遍历所有包含公式的单元格(包括celldata和data数组)
+ * 2. 检查这些单元格是否已经在calcChain中
+ * 3. 如果不在,则添加到calcChain中
+ * 4. 确保计算链的正确性,使所有公式都能正常计算
+ * 
+ * @param {Object} sheet - 单个工作表数据
+ * @returns {Object} 修复后的工作表
+ */
+function fixCalcChain(sheet) {
+  if (!sheet) return sheet
+  
+  // 确保calcChain存在
+  if (!sheet.calcChain) {
+    sheet.calcChain = []
+  }
+  
+  // 创建现有计算链的快速查找映射
+  // 使用 "行_列" 作为键,例如 "10_6" 表示第11行G列
+  const existingCalcMap = new Map()
+  sheet.calcChain.forEach(item => {
+    if (item && typeof item.r === 'number' && typeof item.c === 'number') {
+      const key = `${item.r}_${item.c}`
+      existingCalcMap.set(key, true)
+    }
+  })
+  
+  /**
+   * 辅助函数:添加单元格到计算链
+   * @param {number} row - 行索引(0-based)
+   * @param {number} col - 列索引(0-based)
+   */
+  const addToCalcChain = (row, col) => {
+    const key = `${row}_${col}`
+    
+    // 如果已经存在,跳过
+    if (existingCalcMap.has(key)) {
+      return
+    }
+    
+    // 添加到计算链
+    sheet.calcChain.push({
+      r: row,
+      c: col,
+      index: sheet.index || "0"  // 使用工作表索引,默认为"0"
+    })
+    
+    // 更新映射
+    existingCalcMap.set(key, true)
+  }
+  
+  // 第一步:遍历celldata,查找有公式的单元格
+  if (Array.isArray(sheet.celldata)) {
+    sheet.celldata.forEach(cell => {
+      if (cell && typeof cell.r === 'number' && typeof cell.c === 'number') {
+        // 检查是否有公式
+        const hasFormula = cell.v && cell.v.f
+        if (hasFormula) {
+          addToCalcChain(cell.r, cell.c)
+        }
+      }
+    })
+  }
+  
+  // 第二步:遍历data数组,查找有公式的单元格
+  if (Array.isArray(sheet.data)) {
+    sheet.data.forEach((row, rowIndex) => {
+      if (Array.isArray(row)) {
+        row.forEach((cell, colIndex) => {
+          if (cell && cell.f) {
+            addToCalcChain(rowIndex, colIndex)
           }
         })
       }
-      
-      return sheet
     })
-  } catch (error) {
-    return sheetData
   }
+  
+  // 第三步:处理特殊情况 - 检查是否有合并单元格影响公式计算
+  // 如果单元格是合并单���格的一部分,可能需要特殊处理
+  if (sheet.config && sheet.config.merge) {
+    // 可以在这里添加合并单元格的特殊处理逻辑
+    // 例如:确保合并单元格的主单元格在计算链中
+  }
+  
+  return sheet
 }
 
 /**