Browse Source

导出表格-单元格设置数字格式

zhongxiaoyu 1 year ago
parent
commit
b0f80c5769

+ 101 - 33
src/utils/table.js

@@ -11,13 +11,14 @@ import _ from 'lodash'
 import * as XLSX from 'xlsx'
 import XLSX_STYLE from 'xlsx-style'
 import FileSaver from 'file-saver'
+import { Message } from 'element-ui'
 
 /**
  * @description: 表格行合并
  * @param {Object} config
  * @return {Array}
  */
-export function mergeTableRow (config) {
+export function mergeTableRow(config) {
   let data = config.data
   const { mergeColNames, firstMergeColNames, firstMerge } = config
   if (!mergeColNames || mergeColNames.length === 0) {
@@ -38,17 +39,19 @@ export function mergeTableRow (config) {
           }).length === 0
         if (
           (mcFlag && flag) ||
-          (flag && data[index][firstMerge + '-span'] && data[index][firstMerge + '-span'].rowspan === 1)
+          (flag &&
+            data[index][firstMerge + '-span'] &&
+            data[index][firstMerge + '-span'].rowspan === 1)
         ) {
           v[m + '-span'] = {
             rowspan: 1,
-            colspan: 1
+            colspan: 1,
           }
         } else {
           data[mList[rowVal]['index']][m + '-span'].rowspan++
           v[m + '-span'] = {
             rowspan: 0,
-            colspan: 0
+            colspan: 0,
           }
           mList[rowVal]['num']++
           mList[rowVal]['newIndex']++
@@ -57,7 +60,7 @@ export function mergeTableRow (config) {
         mList[rowVal] = { num: 1, index: index, newIndex: index + 1 }
         v[m + '-span'] = {
           rowspan: 1,
-          colspan: 1
+          colspan: 1,
         }
       }
       return v
@@ -67,7 +70,7 @@ export function mergeTableRow (config) {
 }
 
 // 表格单元格class设置
-export function commonTableCellClass ({ row, column, rowIndex, columnIndex }) {
+export function commonTableCellClass({ row, column, rowIndex, columnIndex }) {
   const classes = []
   if (['actualDepartureTime', 'actualLandingTime'].includes(column.property)) {
     classes.push('pre-line')
@@ -76,7 +79,7 @@ export function commonTableCellClass ({ row, column, rowIndex, columnIndex }) {
 }
 
 // 获取对应时区的时间
-export function timeInZone (date, timeZone = 0, local = 8) {
+export function timeInZone(date, timeZone = 0, local = 8) {
   if (!(date instanceof Date)) {
     if (typeof date === 'string' && date.length) {
       date = new Date(date)
@@ -85,7 +88,7 @@ export function timeInZone (date, timeZone = 0, local = 8) {
     }
   }
 
-  function formatDate (num) {
+  function formatDate(num) {
     return num < 10 ? '0' + num : num
   }
   const time = date.getTime() + (timeZone - local) * 60 * 60 * 1000
@@ -124,28 +127,28 @@ export function timeInZone (date, timeZone = 0, local = 8) {
 // }
 
 // 表格添加过滤条件
-export function setTableFilters (tableData, filters) {
+export function setTableFilters(tableData, filters) {
   const tempSets = {}
   Object.keys(filters).forEach(key => {
     tempSets[key] = new Set()
   })
   tableData.forEach(item => {
     Object.keys(tempSets).forEach(key => {
-      (item[key] ?? '') !== '' && tempSets[key].add(String(item[key]))
+      ;(item[key] ?? '') !== '' && tempSets[key].add(String(item[key]))
     })
   })
   Object.keys(tempSets).forEach(key => {
     filters[key] = _.orderBy(
       [...tempSets[key]].map(value => ({
         text: value,
-        value
+        value,
       })),
       o => o.value
     )
   })
 }
 
-function devideGroup (cellName) {
+function devideGroup(cellName) {
   const stringArray = cellName.split('')
   const length = stringArray.length
   let index = 0
@@ -155,32 +158,40 @@ function devideGroup (cellName) {
     } else {
       return {
         columnIndex: index,
-        rowIndex: Number(stringArray.slice(i).join('')) - 1
+        rowIndex: Number(stringArray.slice(i).join('')) - 1,
       }
     }
   }
 }
 
-export function exportToExcel (table, tableName, fileName, headerRowNumber = 1) {
+export function exportToExcel(table, tableName, fileName, headerRowNumber = 1) {
   try {
     // 设置了列的fixed属性后会有两个table元素,导出数据会重复,需要去掉一个table
     const fixedTable = table.querySelector('.el-table__fixed')
     fixedTable && table.removeChild(fixedTable)
     // 自定义的表头里包含筛选,直接导出会把筛选的下拉数据也写到表头单元格里,需要先去掉筛选弹出框
-    const tableHeaderCellPopovers = table.querySelectorAll('.table-header-cell-popover')
+    const tableHeaderCellPopovers = table.querySelectorAll(
+      '.table-header-cell-popover'
+    )
     tableHeaderCellPopovers.forEach(node => {
       node.removeChild(node.querySelector('.el-popover'))
     })
     // 生成要导出的xlsx数据,raw: true表示不使用excel的格式解析,输出为纯文本,sheet设置xlsx这一页的标题
-    const tableBook = XLSX.utils.table_to_book(table, { raw: true, sheet: tableName })
+    const tableBook = XLSX.utils.table_to_book(table, {
+      raw: true,
+      sheet: tableName,
+    })
     // 计算每一列的单元格的最大宽度(包含表头),单元格的key为'A12'、'AA2'等,和excel里一致
     const xlsxDatas = tableBook.Sheets[tableName]
     const columnWidths = []
+    const reg = /^[A-Z]+([\d]+$)/
     for (const cellName in xlsxDatas) {
-      if (!['!rows', '!cols', '!fullref', '!ref', '!merges'].includes(cellName)) {
+      const match = cellName.match(reg)
+      if (match) {
+        const cellValue = xlsxDatas[cellName].v
         const { columnIndex, rowIndex } = devideGroup(cellName)
         const cellWidth = Math.max(
-          ...xlsxDatas[cellName].v
+          ...cellValue
             .toString()
             .split('\n')
             .map(cellRow =>
@@ -190,22 +201,25 @@ export function exportToExcel (table, tableName, fileName, headerRowNumber = 1)
               }, 0)
             )
         )
-        if ((!columnWidths[columnIndex] && cellWidth > 0) || cellWidth > columnWidths[columnIndex]) {
+        if (
+          (!columnWidths[columnIndex] && cellWidth > 0) ||
+          cellWidth > columnWidths[columnIndex]
+        ) {
           columnWidths[columnIndex] = cellWidth
         }
         let cellStyle = {
           alignment: {
             horizontal: 'center',
             vertical: 'center',
-            wrapText: true
-          }
+            wrapText: true,
+          },
         }
         if (rowIndex < headerRowNumber) {
           const borderStyle = {
             style: 'medium',
             color: {
-              rgb: 'FFFFFF'
-            }
+              rgb: 'FFFFFF',
+            },
           }
           cellStyle = {
             ...cellStyle,
@@ -213,36 +227,90 @@ export function exportToExcel (table, tableName, fileName, headerRowNumber = 1)
               top: borderStyle,
               right: borderStyle,
               bottom: borderStyle,
-              left: borderStyle
+              left: borderStyle,
             },
             font: {
               color: {
-                rgb: 'FFFFFF'
-              }
+                rgb: 'FFFFFF',
+              },
             },
             fill: {
               fgColor: {
-                rgb: '3366FF'
-              }
-            }
+                rgb: '3366FF',
+              },
+            },
           }
         } else {
           cellStyle.alignment.horizontal = 'left'
+          
+          const isNumber = !isNaN(parseFloat(cellValue)) && isFinite(cellValue)
+          if (isNumber) {
+            xlsxDatas[cellName] = {
+              ...xlsxDatas[cellName],
+              t: 'n',
+              z: '0',
+              v: Number(cellValue),
+            }
+          }
+          const isPercentage = /^\d+(\.\d+){0,1}\%$/.test(cellValue)
+          if (isPercentage) {
+            xlsxDatas[cellName] = {
+              ...xlsxDatas[cellName],
+              t: 'n',
+              z: '0.00%',
+              v: parseFloat(cellValue),
+            }
+          }
+          // const date = '\\d{4}\\-\\d{2}\\-\\d{2}'
+          // const time = '\\d{2}\\:\\d{2}\:\\d{2}'
+          // const dateReg = new RegExp(`^${date}$`)
+          // const timeReg = new RegExp(`^${time}$`)
+          // const datetimeReg = new RegExp(`^${date} ${time}$`)
+          // const isDate = dateReg.test(cellValue)
+          // const isTime = timeReg.test(cellValue)
+          // const isDatetime = datetimeReg.test(cellValue)
+          // if (isDate) {
+          //   xlsxDatas[cellName] = {
+          //     ...xlsxDatas[cellName],
+          //     t: 'd',
+          //     z: 'yyyy-MM-dd',
+          //     v: new Date(cellValue),
+          //   }
+          // }
+          // if (isTime) {
+          //   xlsxDatas[cellName] = {
+          //     ...xlsxDatas[cellName],
+          //     t: 'd',
+          //     z: 'HH:mm:ss',
+          //     v: new Date(cellValue),
+          //   }
+          // }
+          // if (isDatetime) {
+          //   xlsxDatas[cellName] = {
+          //     ...xlsxDatas[cellName],
+          //     t: 'd',
+          //     z: 'yyyy-MM-dd HH:mm:ss',
+          //     v: new Date(cellValue),
+          //   }
+          // }
         }
         xlsxDatas[cellName].s = cellStyle
       }
     }
     xlsxDatas['!cols'] = columnWidths.map(width => ({
-      wch: width + 2
+      wch: width + 2,
     }))
     const tableWrite = XLSX_STYLE.write(tableBook, {
       bookType: 'xlsx',
       bookSST: true,
       type: 'buffer',
-      cellStyles: true
+      cellStyles: true,
     })
-    FileSaver.saveAs(new Blob([tableWrite], { type: 'application/octet-stream' }), fileName)
+    FileSaver.saveAs(
+      new Blob([tableWrite], { type: 'application/octet-stream' }),
+      fileName
+    )
   } catch (error) {
-    this.$message.error(error.message);
+    Message.error(error.message)
   }
 }

+ 2 - 2
src/views/newScene/components/advanceQuery.vue

@@ -74,7 +74,7 @@ import SimpleTable from '@/components/SimpleTable'
 import Dialog from '@/layout/components/Dialog'
 import { parseTime } from '@/utils/index'
 import { Query } from '@/api/dataIntegration'
-import { throttledExportToExcel } from '@/utils/table'
+import { exportToExcel } from '@/utils/table'
 const comparisonOperatorOptions = [
   {
     label: '小于等于',
@@ -730,7 +730,7 @@ export default {
       }
       const table = this.$refs[refName].$el.cloneNode(true)
       const fileName = `${tableName}.xlsx`
-      throttledExportToExcel(table, tableName, fileName)
+      exportToExcel(table, tableName, fileName)
     }
   }
 }

+ 21 - 2
src/views/statisticsCharts/components/commonBarStatisticsCharts.vue

@@ -501,9 +501,9 @@ export default {
       }
       const reg = /^[A-Z]+([\d]+$)/
       for (const key in sheet) {
-        const match = reg.test(key)
+        const match = key.match(reg)
         if (match) {
-          const rowIndex = reg.exec(key)[1]
+          const rowIndex = match[1]
           let cellStyle = {
             alignment: {
               horizontal: 'center',
@@ -534,6 +534,25 @@ export default {
           } else {
             cellStyle.alignment.horizontal = 'left'
           }
+          const cellValue = sheet[key].v
+          const isNumber = !isNaN(parseFloat(cellValue)) && isFinite(cellValue)
+          const isPercentage = /^[0-9]+(\.[0-9]+){0,1}\%$/.test(cellValue)
+          if (isNumber) {
+            sheet[key] = {
+              ...sheet[key],
+              t: 'n',
+              z: '0',
+              v: Number(cellValue)
+            }
+          }
+          if (isPercentage) {
+            sheet[key] = {
+              ...sheet[key],
+              t: 'n',
+              z: '0.00%',
+              v: parseFloat(cellValue)
+            }
+          }
           sheet[key].s = cellStyle
         }
       }