前端 Excel 工具组件实战:导入 → 可编辑表格 → 导出 + 样式同步 + 单元格合并
目录
- 1. 项目初始化与依赖安装
- 2. 表格组件设计(基于 Handsontable)
- 3. 导入功能:支持 `.xlsx` / `.csv`
- 4. 导出功能:带样式 & 合并信息
- 5. 样式同步实现方案
- 6. 合并单元格功能逻辑
- 7. 拓展功能建议 + 示例代码
- ✅ 设置单元格背景色按钮
- ✅ 支持 JSON 数据导出保存
1. 项目初始化与依赖安装
npm init vite@latest excel-editor --template vue-ts
cd excel-editor
npm install
npm install xlsx file-saver handsontable @handsontable/vue
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
在 main.ts
中引入 Tailwind:
import './index.css'
2. 表格组件设计(基于 Handsontable)
我们封装一个 ExcelEditor.vue
组件,使用 @handsontable/vue
:
<template> <hot-table ref="hotTableRef" :settings="settings" licenseKey="non-commercial-and-evaluation" />
</template> <script setup lang="ts">
import { ref } from 'vue'
import { HotTable } from '@handsontable/vue'
import Handsontable from 'handsontable' const hotTableRef = ref()
const settings = { data: Handsontable.helper.createEmptySpreadsheetData(20, 10), rowHeaders: true, colHeaders: true, contextMenu: true, mergeCells: [], manualRowResize: true, manualColumnResize: true, comments: true, cells(row: number, col: number) { return { className: '' } }
}
</script>
3. 导入功能:支持 .xlsx
/ .csv
import * as XLSX from 'xlsx' const handleFileUpload = (file: File) => { const reader = new FileReader() reader.onload = (e) => { const data = new Uint8Array(e.target!.result as ArrayBuffer) const workbook = XLSX.read(data, { type: 'array' }) const sheet = workbook.Sheets[workbook.SheetNames[0]] const json = XLSX.utils.sheet_to_json(sheet, { header: 1 }) hotTableRef.value.hotInstance.loadData(json) } reader.readAsArrayBuffer(file)
}
4. 导出功能:带样式 & 合并信息
import { saveAs } from 'file-saver' const exportToExcel = () => { const hot = hotTableRef.value.hotInstance const data = hot.getData() const ws = XLSX.utils.aoa_to_sheet(data) const merges = hot.getPlugin('mergeCells').mergedCellsCollection.mergedCells ws['!merges'] = merges.map(m => ({ s: { r: m.row, c: m.col }, e: { r: m.row + m.rowspan - 1, c: m.col + m.colspan - 1 } })) const wb = XLSX.utils.book_new() XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) saveAs(new Blob([wbout]), 'table.xlsx')
}
5. 样式同步实现方案
const cellStyles = new Map<string, any>() const updateCellStyle = (row: number, col: number, style: any) => { const key = `${row}_${col}` cellStyles.set(key, style)
} cells(row, col) { const key = `${row}_${col}` const style = cellStyles.get(key) || {} return { renderer(hotInstance, td, row, col, prop, value) { td.style.backgroundColor = style.backgroundColor || '' td.style.fontWeight = style.fontWeight || '' td.innerText = value return td } }
}
6. 合并单元格功能逻辑
const mergeSelectedCells = () => { const hot = hotTableRef.value.hotInstance const selected = hot.getSelectedLast() if (!selected) return const [startRow, startCol, endRow, endCol] = selected hot.getPlugin('mergeCells').merge({ row: Math.min(startRow, endRow), col: Math.min(startCol, endCol), rowspan: Math.abs(endRow - startRow) + 1, colspan: Math.abs(endCol - startCol) + 1, }) hot.render()
}
7. 拓展功能建议 + 示例代码
✅ 设置单元格背景色按钮
<button @click="setCurrentCellStyle({ backgroundColor: '#ffff99' })"> 高亮当前单元格
</button> const setCurrentCellStyle = (style: any) => { const hot = hotTableRef.value.hotInstance const [row, col] = hot.getSelectedLast() || [] updateCellStyle(row, col, style) hot.render()
✅ 支持 JSON 数据导出保存
const getJsonData = () => { const data = hotTableRef.value.hotInstance.getData() return JSON.stringify(data)
}
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕