Skip to content

实现 Excel 互转 工具

分类:developer | 标签:Excel、xlsx、转换 Excel 与 JSON/CSV 互相转换

2.1 功能说明

Excel 与 JSON/CSV 互相转换

2.1.1 使用指南

功能说明

本地解析 Excel(.xlsx/.xls),多 Sheet 预览并转为 JSON / CSV;也可将 JSON 数组或 CSV 文本生成为 Excel 文件下载。全程在浏览器完成,不上传服务器。

使用场景

表格数据格式转换、接口数据 mock、报表导出。

2.2 代码实现

2.2.1 组件结构

本工具是一个基于 Vue 3 <script setup> 语法的单文件组件(SFC),统一包裹在 ToolPageShell 组件内,由它提供页面标题、工具 ID、分类与「使用指南」插槽等通用外壳;核心业务逻辑(响应式状态、计算属性、事件处理函数)全部写在 <script setup> 中,输入/输出通过 el-inputel-button 等 Element Plus 组件与用户交互,所有数据均在浏览器本地处理,不会上传服务器。

2.2.2 核心逻辑概览

<script setup> 中定义的主要函数/方法:

  • onFile()
  • renderSheet()
  • copyOut()
  • download()
  • save()
  • genExcel()

2.2.3 关键实现代码

以下是该工具的完整 <script setup> 实现(核心代码)。模板(<template>)与样式(<style>)已省略。

vue
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import XLSX from '@/vendor/xlsx/xlsx.full.min.js'
import ToolPageShell from '@/components/ToolPageShell.vue'

const tab = ref('toJson')
const err = ref('')
const sheetNames = ref([])
const sheet = ref('')
const jsonOut = ref('')
const csvOut = ref('')
const preview = ref([])
const previewCols = ref([])
let wb = null

const inFmt = ref('json')
const inText = ref('')
const outSheet = ref('Sheet1')

function onFile(e) {
  err.value = ''; sheetNames.value = []; jsonOut.value = ''; csvOut.value = ''
  const f = e.target.files && e.target.files[0]
  if (!f) return
  if (!/\.(xlsx|xls)$/i.test(f.name)) { err.value = '请选择 .xlsx 或 .xls 文件'; return }
  f.arrayBuffer().then(buf => {
    wb = XLSX.read(new Uint8Array(buf), { type: 'array' })
    sheetNames.value = wb.SheetNames
    sheet.value = wb.SheetNames[0]
    renderSheet()
  }).catch(er => { err.value = '读取失败:' + er.message })
}

function renderSheet() {
  if (!wb || !sheet.value) return
  const ws = wb.Sheets[sheet.value]
  const rows = XLSX.utils.sheet_to_json(ws, { defval: '', header: 1 })
  jsonOut.value = JSON.stringify(XLSX.utils.sheet_to_json(ws, { defval: '' }), null, 2)
  csvOut.value = XLSX.utils.sheet_to_csv(ws)
  const head = (rows[0] || []).map((_, i) => '列' + (i + 1))
  previewCols.value = head
  preview.value = rows.slice(0, 50).map(r => {
    const o = {}
    head.forEach((_, i) => { o[i] = r[i] ?? '' })
    return o
  })
}

function copyOut(t) {
  const v = t === 'json' ? jsonOut.value : csvOut.value
  if (v) navigator.clipboard?.writeText(v).then(() => ElMessage.success('已复制'))
}
function download(t) {
  if (t === 'json') {
    const blob = new Blob([jsonOut.value], { type: 'application/json;charset=utf-8' })
    save(blob, (sheet.value || 'sheet') + '.json')
  } else {
    const blob = new Blob(['\ufeff' + csvOut.value], { type: 'text/csv;charset=utf-8' })
    save(blob, (sheet.value || 'sheet') + '.csv')
  }
}
function save(blob, name) {
  const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = name; a.click(); URL.revokeObjectURL(a.href)
}

function genExcel() {
  err.value = ''
  const raw = inText.value.trim()
  if (!raw) { err.value = '请输入数据'; return }
  let aoa
  try {
    if (inFmt.value === 'json') {
      const data = JSON.parse(raw)
      if (!Array.isArray(data) || !data.length) throw new Error('需为对象数组')
      const headers = [...new Set(data.flatMap(o => Object.keys(o)))]
      aoa = [headers, ...data.map(o => headers.map(h => o[h] ?? ''))]
    } else {
      const lines = raw.split(/\r?\n/).filter(l => l.trim() !== '')
      aoa = lines.map(l => l.split(','))
    }
  } catch (e) { err.value = '解析失败:' + e.message; return }
  const ws = XLSX.utils.aoa_to_sheet(aoa)
  const book = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(book, ws, outSheet.value || 'Sheet1')
  const out = XLSX.write(book, { type: 'array', bookType: 'xlsx' })
  save(new Blob([out], { type: 'application/octet-stream' }), 'export.xlsx')
  ElMessage.success('已生成 Excel')
}

2.3 效果截图

Excel 互转 效果截图

工具访问地址:https://www.i91tools.com/tools/excel-convert