纯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 下载。


相关推荐
刘发财7 小时前
前端2秒生成500页矢量PDF,rust真的强到没朋友
前端·javascript·rust
lsswear7 小时前
Python 并发 线程
开发语言·python
郑州光合科技余经理7 小时前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
软件课代表CiCi7 小时前
运行库是什么?电脑缺运行库怎么办?c++运行库缺失修复全攻略
开发语言·c++·windows·电脑·dll修复·dll丢失·运行库
梦想平凡8 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
Ivanqhz8 小时前
MLIR OpBuilder
开发语言·python·mlir
红宝村村长9 小时前
windows笔记本双系统ubuntu设置
开发语言
菜鸟~noob23310 小时前
【电子战】第15篇:混合定位——TDOA/FDOA/AOA 联合【含matlab代码】
开发语言·matlab
kyriewen11 小时前
我花3天抓了一个幽灵bug,凶手藏在第4层
前端·javascript·程序员
Dreams_l12 小时前
死信队列和延迟队列介绍
java·开发语言