就那么几个函数实现一个前端导出Excel的功能

632 阅读4分钟

前言:

首先我想描述一下我想实现的需求:需求很简单,我想在自己的项目中实现一个最简单且可用的excel导出功能,而且后续并不会有需求变更,除了导出数据不会有更复杂的操作

实现思路介绍:

  1. 第一种实现思路:先将数据重组成一个表格,然后将重组后的表格塞入html的body中,通过Blob转化成excel的类型然后进行下载即可。 具体实现:
/**
 * @description: 一个原生导出excel的工具(针对:可用即可的需求)
 * @param {string} name 文件名
 * @param {array} list 列表数据 [{}]
 * @param {array} column 表头数据-数据格式要求[{label: '标题', prop: 'title'}]
 * @return {file} 输出一个正在下载的excel文件
 */
export const exportExcel = (name, list, column) => {
    let html = setHtml(list, column)
    let blob = new Blob([html], {
      type: "application/vnd.ms-excel"
    });
    let a = document.createElement('a');
    let url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = name + '.xls'
    a.click();
    a.remove();
}
/**
 * @description: 拼接出表格片段
 * @param {array} list 列表数据 [{}]
 * @param {array} column 表头数据-数据格式要求[{label: '标题', prop: 'title'}]
 * @return {html} 返回一个表格的html片段
 */
const setTable = (list, column) => {
  // 表头构建
  let th = ''
  let col = ''
  column.forEach(item => {
    th += '<th style="background: yellow;color:red;">' + item.label + '</th>'
  })
  col = '<tr>' + th + '</tr>'
  let td = ''
  // 表格内容
  let content = ''
  list.forEach(i => {
    column.forEach(j => {
      td += '<td>' + i[j.prop] + '</td>'
    })
    content = '<tr>' + td + '</tr>'
  })
  let table  = '<table id="my-table" border="1" style="display: none;">' + col + content + '</table>' 
  return table
}
/**
 * @description: 拼接出html片段
 * @param {array} list 列表数据 [{}]
 * @param {array} column 表头数据-数据格式要求[{label: '标题', prop: 'title'}]
 * @return {html} 将table塞进html之后的完整片段
 */
const setHtml = (list, column) => {
  let table = setTable(list, column)
  let html =
    `<!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
    </head>
    <body>
      ${table}
    </body>
    </html>`;
  return html;
}

注:这样操作的前置条件是表格必须满足elementUI的表格被二次封装过,表头需要成[{label: '标题', prop: 'title'}]的形式,其中label为表头的文字,prop为当前列对应的字段名

这样做存在的问题:

如果是使用的电脑自带的office则会出现这种问题,如果是用的wps office则不会.但是点击是的话,是可以正常访问的,但内部表格显示也存在一定问题,于是需要解决这个问题

微信截图_20220308223302.png

微信图片_20220308223903.png

第二种实现思路是使用xlsx的插件,就这一个插件就足矣,我的直觉就告诉我这是一个处理excel格式问题的插件。处理方式更简单,先拼接处完整的table格式的html片段,然后将其数据通过插件导出到excel即可。(详情可搜索npm,点开网站后再搜索这个插件)

  1. 安装
// (如果没用cnpm,请使用你安装的工具)
cnpm install xlsx
  1. 引入
var XLSX = require("xlsx");
  1. 具体实现:
/**
 * @description: 采用xlsx实现导出(针对:可用即可的需求)
 * @param {string} name 文件名
 * @param {array} list 列表数据 [{}]
 * @param {array} column 表头数据-数据格式要求[{label: '标题', prop: 'title'}]
 * @return {file} 输出一个正在下载的excel文件
 */
export const exportExcel = (name, list, column) => {
   // 获取表格html片段
    var table = setTable(list, column)
    // 提取数据(从表中创建一个工作簿对象)
    var workbook = XLSX.utils.table_to_book(table);
    // 处理数据
    var ws = workbook.Sheets["Sheet1"];
    // 打包和发布数据(`writeFile` 尝试写入和保存 XLSB 文件)
    XLSX.writeFile(workbook, name + ".xlsx"); 
}
/**
 * @description: 拼接出表格片段
 * @param {array} list 列表数据 [{}]
 * @param {array} column 表头数据-数据格式要求[{label: '标题', prop: 'title'}]
 * @return {html} 返回一个表格的html片段
 */
const setTable = (list, column) => {
  // 表头构建
  let th = ''
  let col = ''
  column.forEach(item => {
    th += '<th>' + item.label + '</th>'
  })
  col = '<tr>' + th + '</tr>'
  let td = ''
  // 表格内容
  let content = ''
  list.forEach(i => {
    column.forEach(j => {
      td += '<td>' + i[j.prop] + '</td>'
    })
    content = '<tr>' + td + '</tr>'
  })
  let table
  table = document.createElement('table');//创建HTML标签
  table.innerHTML = col + content;//文本节点追加到HTML标签中
  return table
}

导出后的效果:

微信图片_20220308233020.png

参考文献:

  1. npm - xlsx
  2. 使用原生js 来导出excel

后记:

这仅仅是纯前端导入,功能做的很基础,可扩展。实际上,并不用动态去生成table的html,直接通过class获取到页面中的表格,进行导出也可以,但是如果表格第一列有复选框,则会出现空位的情况,我需要导出的表格第一列就有复选框,所以没有这样做。这只是excel导出的其中一种方式:纯前端导出,还有导出excel的文件流,以及导出excel的文件等两种方式,文件要么window.open要么用ajax进行下载即可,文件流由于我不会写这样的接口,所以暂时做不了。写的很烂的原创文章,各位大佬轻点儿喷!