Newer
Older
sensorHubPlusFront / src / utils / exportXlsx.ts
liyaguang 8 days ago 3 KB 页面搭建
import * as XLSX from 'xlsx'

/*
    * @description:
    * @param {Object} json 服务端发过来的数据
    * @param {String} name 导出Excel文件名字
    * @param {String} titleArr 导出Excel表头
    * @param {String} sheetName 导出sheetName名字
    * @return:
    */
export interface excelType {
  json: object
  name: string
  titleArr: string[]
  sheetName: string
}
export function exportExcel(params: excelType) {
  /* convert state to workbook */
  const data = []
  const keyArray = []
  const getLength = function (obj: object) {
    let count = 0
    for (const i in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, i)) {
        // if (obj.hasOwnProperty(i)) {
        count++
      }
    }
    return count
  }
  for (const key1 in params.json) {
    if (Object.prototype.hasOwnProperty.call(params.json, key1)) {
      const element = (params.json as { [key: string]: object })[key1]
      const rowDataArray = []
      for (const key2 in element) {
        if (Object.prototype.hasOwnProperty.call(element, key2)) {
          const element2 = (element as { [key: string]: object })[key2]
          rowDataArray.push(element2)
          if (keyArray.length < getLength(element)) {
            keyArray.push(key2)
          }
          // console.log(keyArray, 'keyArray')
        }
      }
      data.push(rowDataArray)
    }
  }
  // keyArray为英文字段表头
  data.splice(0, 0, keyArray as any, params.titleArr as any)
  // console.log('data', data)
  const ws = XLSX.utils.aoa_to_sheet(data)
  const wb = XLSX.utils.book_new()
  // 表头样式(灰色背景、加粗字体、居中对齐)
  const headerStyle = {
    fill: {
      fgColor: { rgb: 'D3D3D3' }
    },
    font: {
      bold: true,
      sz: 12, // 字体大小
      color: { rgb: '000000' }
    },
    alignment: {
      horizontal: 'center',
      vertical: 'center'
    },
    border: {
      top: { style: 'thin', color: { rgb: '000000' } },
      bottom: { style: 'thin', color: { rgb: '000000' } },
      left: { style: 'thin', color: { rgb: '000000' } },
      right: { style: 'thin', color: { rgb: '000000' } }
    }
  }

  // 数据样式(居中对齐、边框)
  const dataStyle = {
    alignment: {
      horizontal: 'center',
      vertical: 'center'
    },
  }
  // 此处隐藏英文字段表头
  const wsrows = [{ hidden: true }]
  /* 设置worksheet每列的最大宽度 */
  const colWidth = data.map(row => row.map((val) => {
    /* 先判断是否为null/undefined */
    if (val == null) {
      return {
        wch: 10,
      }
    }
    /* 再判断是否为中文 */
    else if (val.toString().charCodeAt(0) > 255) {
      return {
        wch: val.toString().length * 2,
      }
    }
    else {
      return {
        wch: val.toString().length,
      }
    }
  }))
  // 获取表格范围
  const range = XLSX.utils.decode_range(ws['!ref']);
  console.log(range, 'range')

  // 应用表头样式(第二行,因为第一行被隐藏)
  for (let c = range.s.c; c <= range.e.c; c++) {
    const cellAddress = XLSX.utils.encode_cell({ r: 1, c });
    if (ws[cellAddress]) ws[cellAddress].s = headerStyle;
  }

  // 应用数据样式(从第三行开始)
  for (let r = 2; r <= range.e.r; r++) {
    for (let c = range.s.c; c <= range.e.c; c++) {
      const cellAddress = XLSX.utils.encode_cell({ r, c });
      if (ws[cellAddress]) ws[cellAddress].s = dataStyle;
    }
  }
  /* 以第一行为初始值 */
  const result = colWidth[0]
  for (let i = 1; i < colWidth.length; i++) {
    for (let j = 0; j < colWidth[i].length; j++) {
      if (result[j].wch < colWidth[i][j].wch) {
        result[j].wch = colWidth[i][j].wch
      }
    }
  }
  ws['!cols'] = result
  ws['!rows'] = wsrows // ws - worksheet
  XLSX.utils.book_append_sheet(wb, ws, params.sheetName)

  /* generate file and send to client */
  XLSX.writeFile(wb, `${params.name}.xlsx`, { bookType: 'xlsx', type: 'array' })
}