Bladeren bron

修复luckysheet导入时,空行空列过多导致保存到后台时超长报错

huangws 17 uur geleden
bovenliggende
commit
25ef0bd909
1 gewijzigde bestanden met toevoegingen van 133 en 11 verwijderingen
  1. 133 11
      src/views/component/onlineSheet/onlineSheetData.vue

+ 133 - 11
src/views/component/onlineSheet/onlineSheetData.vue

@@ -222,23 +222,23 @@ export default {
     // 导入文件
     async importFile(file) {
       try {
-        // 显示加载状态
         const loading = this.$loading({
           lock: true,
           text: '正在导入Excel文件...',
           spinner: 'el-icon-loading',
           background: 'rgba(0, 0, 0, 0.7)'
         })
-        
+
         try {
-          // 使用导入模块处理文件
           const sheetData = await importExcelFile(file)
-          
-          if (sheetData && sheetData.length > 0) {
-            // 更新本地数据并发送到iframe显示
-            this.sheetData = sheetData
+
+          // 裁剪每个 sheet 的空行空列
+          const trimmedSheetData = this.trimSheetData(sheetData)
+
+          if (trimmedSheetData && trimmedSheetData.length > 0) {
+            this.sheetData = trimmedSheetData
             this.sendToIframe('setData', this.sheetData)
-            this.$message.success(`导入成功!共 ${sheetData.length} 个 Sheet`)
+            this.$message.success(`导入成功!共 ${trimmedSheetData.length} 个 Sheet`)
             // 导入后不自动保存,等待用户点击保存按钮
           } else {
             this.$message.error('导入失败:Excel 文件为空或格式错误!')
@@ -247,7 +247,6 @@ export default {
           this.$message.error(`导入失败:${error.message || '文件解析错误,请检查文件格式是否正确'}`)
         } finally {
           loading.close()
-          // 清空文件选择器
           if (this.$refs.fileInput) {
             this.$refs.fileInput.value = ''
           }
@@ -269,11 +268,14 @@ export default {
           
           // 标记为内部更新,避免循环
           this.isUpdatingFromParent = true
+
+          // 保存前先裁剪一次,去掉空行空列
+          const trimmed = this.trimSheetData(this.sheetData)
           
           // 将表格数据以 JSON 字符串格式传递给父组件,key 使用 'biaoGeNeiRong'
           this.$emit('change-data', 'biaoGeNeiRong', JSON.stringify({ 
             sheetId: this.localSheetId, 
-            sheets: this.sheetData 
+            sheets: trimmed 
           }))
           
           // 重置标记
@@ -348,8 +350,10 @@ export default {
       await new Promise(resolve => setTimeout(resolve, 500))
 
       try {
+        //导出前先裁剪一次
+        const trimmed = this.trimSheetData(this.sheetData)
         // 传 fileName 给 exportToExcel
-        const result = await exportToExcel(this.sheetData, fileName)
+        const result = await exportToExcel(trimmed, fileName)
 
         if (result.success) {
           this.$message.success(`导出成功!文件: ${result.fileName}`)
@@ -378,6 +382,124 @@ export default {
 
       // 兜底
       return `在线表格导出_${ym}`
+    },
+    // 裁剪 sheet 数据中的空行空列
+    trimSheetData(sheets) {
+      if (!sheets || !Array.isArray(sheets)) return sheets
+
+      return sheets.map(sheet => {
+        if (!sheet) return sheet
+
+        // 判断单元格是否真的有值(值 / 显示值 / 公式 / 富文本)
+        const hasRealValue = (cell) => {
+          if (!cell || typeof cell !== 'object') return false
+          const v = cell.v
+          if (v && typeof v === 'object' && v !== null) {
+            // celldata 格式
+            if (v.v !== undefined && v.v !== null && v.v !== '') return true
+            if (v.m !== undefined && v.m !== null && v.m !== '') return true
+            if (v.f !== undefined && v.f !== null && v.f !== '') return true
+            if (v.ct && Array.isArray(v.ct.s) && v.ct.s.length > 0) {
+              const txt = v.ct.s
+                .map(x => (x && x.v !== undefined && x.v !== null) ? x.v : '')
+                .join('')
+              if (txt !== '') return true
+            }
+            return false
+          }
+          // data 数组格式
+          if (v !== undefined && v !== null && v !== '') return true
+          if (cell.m !== undefined && cell.m !== null && cell.m !== '') return true
+          if (cell.f !== undefined && cell.f !== null && cell.f !== '') return true
+          if (cell.ct && Array.isArray(cell.ct.s) && cell.ct.s.length > 0) {
+            const txt = cell.ct.s
+              .map(x => (x && x.v !== undefined && x.v !== null) ? x.v : '')
+              .join('')
+            if (txt !== '') return true
+          }
+          return false
+        }
+
+        // 判断是否有"有意义的样式"(背景、字体、字号、边框、非默认格式等)
+        const hasMeaningfulStyle = (cell) => {
+          if (!cell || typeof cell !== 'object') return false
+          const v = (cell.v && typeof cell.v === 'object') ? cell.v : cell
+          if (v.bg) return true                              // 背景色
+          if (v.bd) return true                              // 边框
+          if (v.fc && v.fc !== '#000000') return true        // 字体色非黑
+          if (v.ff && v.ff !== '宋体') return true           // 非默认字体
+          if (v.fs && v.fs !== 11) return true               // 非默认字号
+          if (v.bl === 1 || v.it === 1 || v.un === 1 || v.cl === 1) return true
+          if (v.ct && v.ct.fa && v.ct.fa !== 'General') return true  // 非默认数字格式
+          return false
+        }
+
+        // ========== 处理 celldata ==========
+        if (Array.isArray(sheet.celldata)) {
+          // 先过滤掉"既没值也没意义样式"的垃圾项(如 {tb:1})
+          sheet.celldata = sheet.celldata.filter(item => {
+            if (!item || typeof item.r !== 'number' || typeof item.c !== 'number') return false
+            return hasRealValue(item) || hasMeaningfulStyle(item)
+          })
+        }
+
+        // ========== 重新计算真实行列边界 ==========
+        let maxRow = -1
+        let maxCol = -1
+
+        if (Array.isArray(sheet.celldata)) {
+          sheet.celldata.forEach(item => {
+            if (item.r > maxRow) maxRow = item.r
+            if (item.c > maxCol) maxCol = item.c
+          })
+        }
+
+        if (Array.isArray(sheet.data)) {
+          for (let r = 0; r < sheet.data.length; r++) {
+            const row = sheet.data[r]
+            if (!Array.isArray(row)) continue
+            for (let c = 0; c < row.length; c++) {
+              const cell = row[c]
+              if (cell && (hasRealValue(cell) || hasMeaningfulStyle(cell))) {
+                if (r > maxRow) maxRow = r
+                if (c > maxCol) maxCol = c
+              }
+            }
+          }
+        }
+
+        // 强制重设 row / column(不再有"比大小"的旧逻辑)
+        if (maxRow >= 0 && maxCol >= 0) {
+          sheet.row = maxRow + 1
+          sheet.column = maxCol + 1
+
+          // 同步裁 data 数组
+          if (Array.isArray(sheet.data) && sheet.data.length > sheet.row) {
+            sheet.data = sheet.data.slice(0, sheet.row)
+          }
+          if (Array.isArray(sheet.data)) {
+            sheet.data = sheet.data.map(row =>
+              Array.isArray(row) ? row.slice(0, sheet.column) : row
+            )
+          }
+        } else {
+          // 完全没内容
+          sheet.row = 1
+          sheet.column = 1
+          sheet.celldata = []
+          sheet.data = [[{ v: '' }]]
+        }
+
+        // 裁 rowlen / columnlen
+        if (Array.isArray(sheet.rowlen)) {
+          sheet.rowlen = sheet.rowlen.slice(0, sheet.row)
+        }
+        if (Array.isArray(sheet.columnlen)) {
+          sheet.columnlen = sheet.columnlen.slice(0, sheet.column)
+        }
+
+        return sheet
+      })
     }
   }
 }