当前位置: 首页 > 工具软件 > Any2Excel > 使用案例 >

typescript:一个关于导出excel的简单例子2

罗睿识
2023-12-01

前序

上一次大概讲了下导出execel的比较简单的做法,这回补上一个更简单的方法,就用execel导出的。比较方便,不多叙述

思路

大体思路很简单,就是

1.先将数据放在一个数组中,整理成为一个数组

2.保存到table格式的文本中

3.更新table的数据,走execel的路线进行封装

4.将table转化为流的方式,写进去(二进制的操作,这个是必走之路)

大概难点在三个

1.数组长什么样子?

2.table怎么封装成execel的格式

3.怎么转化为流

代码

代码其实很简单,没有啥,就不废话了,静心下来,看逻辑,是可以看懂的,写的也很直白,没用复杂的写法,可能需要有一定的ts基础,但是我还是觉得写得够多了,注释


    /**
 * @typedef 数组返回拼接字符串格式
 * @param tableRows Array 表格字符串列表
 * @returns fullTemplateStr string 拼接完成的字符串
 */
    private arrayToTableStr(tableRows: Array<string>) {
      // 最后完整的字符串内容
      let fullTemplateStr = ''
      //拼接整个头部
      fullTemplateStr += template.head

      // 增加sheet的头部
      fullTemplateStr += template.sheet.head
      // 加上内容
      fullTemplateStr += 'sheet1'
      // 增加sheet的尾部
      fullTemplateStr += template.sheet.tail

      // 增加上中间的部分
      fullTemplateStr += template.mid
      fullTemplateStr += template.table.head
      // 加上正式内容
      tableRows.forEach((row) => {
        fullTemplateStr += row
      })
      fullTemplateStr += template.table.tail

      //拼接整个尾部
      fullTemplateStr += template.foot
      return fullTemplateStr
    }
    /**
     * @typedef a链接导出
     * @param fileName  文件名称
     * @param linkUrl   链接
     * @param fileExtension   文件后缀
     */
    private createLink(linkUrl: string, fileName?: String, fileExtension?: FileType) {
      fileExtension = fileExtension || FileType.xml//默认类型为xml
      let aTag = document.createElement('a')
      aTag.download = `${fileName || this.fileName}.${fileExtension}`
      document.body.appendChild(aTag)
      aTag.href = linkUrl
      aTag.click()
      document.body.removeChild(aTag)
    }

    /**
     * @description 将表格的每一项创建并添加到数据中
     * @param titleArray Array 标题列表
     * @param jsonData 内容体
     * @param styleList 样式列表
     */
    private createRowArray(titleArray: Array<string>, jsonData: Array<string>, styleList?: any) {

      const tableRows = []//放数据的地方
      // let computedStyle = {}//计算过后的样式对象
      let row = ''
      // 需要把头的也遍历一边,后面需要拼接
      // row += `<tr style=' ${computedStyle} '>`
      row += '<tr>'
      // 竖排
      titleArray.forEach(td => {
        row += `<td>${td}</td>`
      })
      row += '</tr>'
      // 每一列都加上去
      tableRows.push(row)
      // 便利获取到样式以及元素的k-v,拼接起来
      // 横排
      jsonData.forEach(tr => {
        row = '<tr>'
        // 竖排
        Object.keys(tr).forEach(td => {
          styleList[td] ? row += `<td${styleList[td]}>${tr[td]}</td>` : row += `<td>${tr[td]}</td>`
        })
        row += '</tr>'
        // 每一列都加上去
        tableRows.push(row)

      })
      return tableRows
    }
    /**
     *@typedef 把样式拼接成字符串的形式
     *@param styleList Array 样式对象 
     */

    private formatStyle2String(styleList: any) {
      if (!styleList || styleList.length === 0) { return [] };
      const _styleList = []

      Object.keys(styleList).forEach((styleKey) => {
        let str = ' style=\''//注意,这儿是空了一个格子的
        Object.keys(styleList[styleKey]).forEach(_o => {
          str += `${_o}:${styleList[styleKey][_o]};`
        })
        str.slice(str.length, 1)//除去最后的空格,毕竟还是要严谨点的
        str += '\' '//注意,最后也是空了一个格子的
        _styleList[styleKey] = str
      })
      return _styleList

    }
    /**
     * @typedef 以table的形式导出execel文件
     * @param titleArray  标题 Array  ['标题1', '标题2', '标题3', '标题4']
     * @param jsonData    内容体  Array  [{k1:v1,k2:v2}]
     */
    public createByTable(titleArray: Array<string>, jsonData: Array<any>, styleList?: Array<Istyle>) {
      const styleArray = this.formatStyle2String(styleList)
      const data = this.createRowArray(titleArray, jsonData, styleArray)
      // 封装成为一个sheet
      let blob = new Blob([this.arrayToTableStr(data)], { type: 'application/vnd.ms-excel' })
      //解决中文乱码问题
      blob = new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type })
      this.createLink(window.URL.createObjectURL(blob), this.fileName, FileType.xls)
      // 遍历数组,获取k-v,
    }

// 枚举类
export enum FileType {
  csv = 'csv',
  xml = 'xml',
  xls = 'xls'
}

// 接口
export interface Ictx {
  worksheet: string,
  table: string,
  sheetName: string
}

export interface IstyleList {
  [name: string]: Istyle
}

// 单个样式的实例
export interface Istyle {
  'text-align': string,
  'background-color': string,
  // ['background-color':string]:string
  width?: string,//宽度 100(px)
  height?: string,//高度 100(px)
  color?: string//颜色 #00ff00
  border: string//border 1px solid #ccc
}
//静态变量
// table转化需要的变量
const utf8Heading = '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
// table的需要模板
export const template = {
  head: '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">' + utf8Heading + '<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets>',
  sheet: {
    head: '<x:ExcelWorksheet><x:Name>',
    tail: '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>'
  },
  mid: '</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body>',
  table: {
    head: '<table>',
    tail: '</table>'
  },
  foot: '</body></html>'
}

备注

使用简单是简单,但是兼容性没做测试,如果实际使用,建议用比较多星的库,或则帮我测测兼容,留言我来改,因为可能是execel导出系列的最后一篇(objectxactive的估计不会写),所以罗索下,最好后台导出,因为前端导出会卡,测试了导出10w条简单的数据,大概需要10s


npm: [aexecel](https://www.npmjs.com/package/aexecel)
github:[aexecel](https://github.com/mkhbz/aexecel)

 

 类似资料: