纯JS 导出 Excel 工具

适用文件:excel.js

适用场景:后台管理系统、列表导出、统计报表导出、后端 Blob 文件下载


1. 能力概览

excel.js 提供 4 类核心能力:

  1. exportExcelByTableHtml:你已经有 <table> 字符串时直接导出
  2. exportExcelByTableElement:页面上已有 table DOM 时直接导出
  3. exportExcelByColumns:传列配置 + 数据,自动拼 table 并导出
  4. exportByAxiosResponse:后端返回 blob 时一键下载

补充基础能力:

  • downloadByDataUri:下载文本内容
  • downloadByBlob:下载 Blob 内容
  • parseFileNameFromDisposition:从响应头解析文件名

2. 安装/接入方式

2.1 本项目内使用

js 复制代码
import {
  exportExcelByTableHtml,
  exportExcelByTableElement,
  exportExcelByColumns,
  exportByAxiosResponse
} from '@/utils/excel'

2.2 复制到任意前端项目

src/utils/excel.js 复制到你的项目中(例如 src/utils/excel.js),然后按实际路径引入即可:

js 复制代码
import { exportExcelByColumns } from './utils/excel'

3. 使用前说明(重要)

  1. 当前方案是 HTML Table 兼容 Excel 的 .xls 导出
  2. 对中文、常规文本、简单样式兼容性好
  3. 如果你需要复杂能力(多 sheet、公式、冻结窗格、复杂样式),建议改用 SheetJS(xlsx
  4. 本工具依赖浏览器环境(window/document),不能在纯 Node 环境直接执行下载

4. 详细示例

4.1 场景A:你已经有 tableHtml 字符串

js 复制代码
import { exportExcelByTableHtml } from '@/utils/excel'

function handleExport() {
  let row = '<table border="1" cellspacing="0" cellpadding="4">'
  row += '<tr><td>序号</td><td>姓名</td><td>分数</td></tr>'
  row += '<tr><td>1</td><td>张三</td><td>95</td></tr>'
  row += '<tr><td>2</td><td>李四</td><td>88</td></tr>'
  row += '</table>'

  exportExcelByTableHtml({
    tableHtml: row,
    fileName: '成绩统计',
    sheetName: '成绩',
    ext: '.xls'
  })
}

4.2 场景B:直接导出页面中已有 table

适用于页面有原生 <table> 或第三方渲染后真实 table DOM。

js 复制代码
import { exportExcelByTableElement } from '@/utils/excel'

function handleExportByDom() {
  exportExcelByTableElement({
    table: '#report-table', // 也可以传 document.querySelector(...) 得到的元素
    fileName: '报表明细',
    sheetName: '明细'
  })
}

模板示例:

html 复制代码
<table id="report-table">
  <tr>
    <td>地区</td>
    <td>参赛队数</td>
  </tr>
  <tr>
    <td>南宁</td>
    <td>12</td>
  </tr>
</table>

4.3 场景C:按列配置导出(推荐)

最通用,建议新页面都用这一种。

js 复制代码
import { exportExcelByColumns } from '@/utils/excel'

function exportTeamSummary(list) {
  exportExcelByColumns({
    title: '参赛队数汇总',
    fileName: '参赛队数汇总',
    sheetName: '汇总',
    emptyText: '--',
    columns: [
      { label: '序号', key: 'index', headerStyle: 'text-align:center;font-weight:bold;' },
      { label: '赛道名称', key: 'proj_name' },
      { label: '承办校', key: 'place_name' },
      { label: '队伍数量', key: 'num' },
      {
        label: '参赛人数',
        key: 'people',
        formatter: (row) => Number(row.people || 0)
      }
    ],
    data: list.map((item, i) => ({
      index: i + 1,
      proj_name: item.proj_name,
      place_name: item.place_name,
      num: item.num,
      people: item.people
    }))
  })
}

formatter 进阶示例

js 复制代码
{
  label: '状态',
  key: 'status',
  formatter: (row) => {
    const map = { 0: '待审核', 1: '通过', 2: '驳回' }
    return map[row.status] || '未知'
  }
}

4.4 场景D:后端 Blob 导出

适用于接口返回文件流,比如 responseType: 'blob'

js 复制代码
import axios from 'axios'
import { exportByAxiosResponse } from '@/utils/excel'

function exportFromApi(params) {
  axios({
    method: 'get',
    url: '/api/report/export',
    params,
    responseType: 'blob'
  }).then((res) => {
    // 优先取响应头文件名;没有时使用兜底名
    exportByAxiosResponse(res, '报表导出.xlsx')
  })
}

4.5 场景E:Vue2 页面完整接入示例

vue 复制代码
<script>
import { exportExcelByColumns } from '@/utils/excel'
import { match_proj_people } from '@/api/xxx'

export default {
  methods: {
    async handleDown() {
      const res = await match_proj_people(this.form)
      const list = (res && res.data && res.data.list) || []

      exportExcelByColumns({
        title: '参赛队数汇总',
        fileName: '参赛队数汇总',
        sheetName: 'Sheet1',
        columns: [
          { label: '序号', key: 'index' },
          { label: '赛道名称', key: 'proj_name' },
          { label: '承办校', key: 'place_name' },
          { label: '参赛队伍数量', key: 'num' },
          { label: '参赛人数', key: 'people', formatter: r => Number(r.people || 0) }
        ],
        data: list.map((item, i) => ({ index: i + 1, ...item }))
      })
    }
  }
}
</script>

5. API 速查

exportExcelByTableHtml(options)

  • tableHtml: string 表格 html
  • fileName?: string 文件名,默认 导出数据
  • sheetName?: string sheet 名,默认 Sheet1
  • ext?: string 后缀,默认 .xls

exportExcelByTableElement(options)

  • table: HTMLElement | string DOM 或选择器(必填)
  • 其他参数同上

exportExcelByColumns(options)

  • title?: string 标题行
  • columns: Array<Column> 列配置(建议必填)
  • data: any[] 行数据(建议必填)
  • emptyText?: string 空值填充值
  • tableAttrs?: string table 标签属性
  • fileName/sheetName/ext 同上

Column 结构:

  • label: string
  • key: string
  • formatter?: (row, rowIndex, col, colIndex) => any
  • headerStyle?: string
  • cellStyle?: string

exportByAxiosResponse(response, fallbackFileName?)

  • response: axios 响应对象(responseType: 'blob'
  • fallbackFileName: 响应头无文件名时的兜底名

6. 常见问题

6.1 为什么导出的不是严格 xlsx?

因为当前实现是 HTML Table 兼容模式(.xls),优点是简单、零依赖;缺点是高级能力有限。

6.2 中文文件名乱码怎么办?

优先让后端在 content-disposition 返回 UTF-8 文件名;前端已做 decodeURIComponent 兼容处理。

6.3 导出值中含有 HTML 标签怎么办?

工具默认做了 HTML 转义,避免内容串结构。若你确实要导出富文本,建议先在业务层做可控转换。

6.4 可以导出大数据量吗?

可以,但前端拼接超大 table 会占内存。大数据导出建议走后端生成文件流,再用 exportByAxiosResponse 下载。


相关推荐
lsx2024062 小时前
MySQL 删除数据表
开发语言
沐知全栈开发2 小时前
XML Schema 复合类型 - 仅含元素
开发语言
weixin_408099672 小时前
跨境电商OCR:3秒识别多语言商品标签
开发语言·图像处理·人工智能·后端·ocr·api·文字识别ocr
小樱花的樱花2 小时前
C++引用:高效编程的技巧
开发语言·数据结构·c++·算法
南境十里·墨染春水2 小时前
C++笔记 继承中重载规则 公有私有继承的区别(面向对象)
开发语言·c++·笔记
遇见你...2 小时前
B03 SpringMVC拦截器
java·开发语言
沉鱼.442 小时前
进制转换题
开发语言·c++·算法
淼淼7632 小时前
QT仪表盘
开发语言·qt
wjcroom2 小时前
融释涡旋理论-对狭义相对论和洛伦兹变换的兼容
开发语言·前端