微信小程序中如何使用xlsx(xlsx.mini.min.js)实现Excel导入导出功能
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、简介</a></li><li><a href="#_label1">二、准备工作</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">1. 下载 xlsx.mini.min.js</a></li><li><a href="#_lab2_1_1">2. 引入库文件</a></li></ul><li><a href="#_label2">三、导出 Excel</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_2">3.1 基本流程</a></li><li><a href="#_lab2_2_3">3.2 完整代码示例</a></li></ul><li><a href="#_label3">四、导入 Excel</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_4">4.1 基本流程</a></li><li><a href="#_lab2_3_5">4.2 完整代码示例</a></li><li><a href="#_lab2_3_6">4.3 重复数据检测示例</a></li></ul><li><a href="#_label4">五、常用 API 说明</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_7">5.1 核心方法</a></li><li><a href="#_lab2_4_8">5.2 工作表属性设置</a></li><li><a href="#_lab2_4_9">5.3 xlsx.write() 选项</a></li><li><a href="#_lab2_4_10">5.4 sheet_to_json() 选项</a></li></ul><li><a href="#_label5">六、注意事项</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、简介</h2><p><code>xlsx.mini.min.js</code> 是 SheetJS 的迷你版本,专门为小程序等轻量级环境设计。本文基于微信小程序环境,详细介绍如何使用该库实现 Excel 文件的导入和导出功能。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、准备工作</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>1. 下载 xlsx.mini.min.js</h3>
<ul><li>访问 SheetJS 官方仓库:https://git.sheetjs.com/sheetjs/sheetjs</li><li>进入 <code>dist</code> 目录,下载 <code>xlsx.mini.min.js</code> 文件,可以只单独下载这个文件就行</li><li>将文件放置到小程序项目的 <code>libs</code> 目录下</li></ul>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2. 引入库文件</h3>
<p>在需要使用 Excel 功能的页面或组件中引入:</p>
<div class="jb51code"><pre class="brush:js;">const xlsx = require("../../libs/xlsx.mini.min")
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>三、导出 Excel</h2>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>3.1 基本流程</h3>
<ol><li><strong>构建数据数组</strong>:将数据组织成二维数组格式</li><li><strong>创建工作表</strong>:使用 <code>xlsx.utils.aoa_to_sheet()</code> 将数组转换为工作表</li><li><strong>设置列宽</strong>(可选):通过 <code>ws['!cols']</code> 设置列宽</li><li><strong>创建工作簿</strong>:使用 <code>xlsx.utils.book_new()</code> 创建新工作簿</li><li><strong>添加工作表</strong>:使用 <code>xlsx.utils.book_append_sheet()</code> 将工作表添加到工作簿</li><li><strong>生成文件</strong>:使用 <code>xlsx.write()</code> 将工作簿转换为 base64 格式</li><li><strong>保存文件</strong>:使用微信小程序的 <code>wx.getFileSystemManager()</code> 保存文件</li></ol>
<p class="maodian"><a name="_lab2_2_3"></a></p><h3>3.2 完整代码示例</h3>
<div class="jb51code"><pre class="brush:js;">exportToExcel() {
const { list } = this.data
if (!list || list.length === 0) {
wx.showToast({
title: '暂无数据可导出',
icon: 'none'
})
return
}
// 1. 构建 Excel 数据表(二维数组)
let sheet = []
// 表头
let titles = ['日期', 'XXXX', 'uuid']
sheet.push(titles)
// 数据行
list.forEach((item) => {
let row = [
item['date'] || '',
item['xxxx'] || '0',
item['uuid'] || ''
]
sheet.push(row)
})
try {
// 2. 将数组转换为工作表
var ws = xlsx.utils.aoa_to_sheet(sheet)
// 3. 设置列宽(可选)
const colWidths = [
{ wch: 15 }, // 日期列:15个字符宽度
{ wch: 15 }, // 总资产列:15个字符宽度
{ wch: 30 }// uuid列:30个字符宽度
]
ws['!cols'] = colWidths
// 4. 创建工作簿
var wb = xlsx.utils.book_new()
// 5. 将工作表添加到工作簿(第三个参数是工作表名称)
xlsx.utils.book_append_sheet(wb, ws, "数据记录")
// 6. 将工作簿转换为 base64 格式
var fileData = xlsx.write(wb, {
bookType: "xlsx",
type: 'base64'
})
// 7. 保存文件
let filePath = `${wx.env.USER_DATA_PATH}/数据记录.xlsx`
const fs = wx.getFileSystemManager()
fs.writeFile({
filePath: filePath,
data: fileData,
encoding: 'base64',
success: (res) => {
const sysInfo = wx.getSystemInfoSync()
// PC 端导出
if (sysInfo.platform.toLowerCase().indexOf('windows') >= 0) {
wx.saveFileToDisk({
filePath: filePath,
success: () => {
wx.showToast({
title: '导出成功',
icon: 'success'
})
},
fail: () => {
wx.showToast({
title: '导出失败',
icon: 'none'
})
}
})
} else {
// 手机端导出 - 打开文档
wx.openDocument({
filePath: filePath,
showMenu: true,
success: () => {
wx.showToast({
title: '导出成功',
icon: 'success'
})
},
fail: () => {
wx.showToast({
title: '导出失败',
icon: 'none'
})
}
})
}
},
fail: (res) => {
if (res.errMsg && res.errMsg.indexOf('locked') >= 0) {
wx.showModal({
title: '提示',
content: '文档已打开,请先关闭',
})
} else {
wx.showToast({
title: '导出失败',
icon: 'none'
})
}
}
})
} catch (error) {
console.error('导出 Excel 失败:', error)
wx.showToast({
title: '导出失败',
icon: 'none'
})
}
}
</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>四、导入 Excel</h2>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>4.1 基本流程</h3>
<ol><li><strong>选择文件</strong>:使用 <code>wx.chooseMessageFile()</code> 选择 Excel 文件</li><li><strong>读取文件</strong>:使用 <code>wx.getFileSystemManager().readFile()</code> 读取文件内容(base64 格式)</li><li><strong>解析 Excel</strong>:使用 <code>xlsx.read()</code> 解析文件</li><li><strong>转换为 JSON</strong>:使用 <code>xlsx.utils.sheet_to_json()</code> 将工作表转换为 JSON 数组</li><li><strong>处理数据</strong>:解析 JSON 数据并转换为应用所需格式</li><li><strong>保存数据</strong>:将处理后的数据保存到本地存储</li></ol>
<p class="maodian"><a name="_lab2_3_5"></a></p><h3>4.2 完整代码示例</h3>
<div class="jb51code"><pre class="brush:js;">importFromExcel() {
// 1. 选择文件
wx.chooseMessageFile({
count: 1,
type: 'file',
extension: ['xlsx', 'xls'],
success: (res) => {
const file = res.tempFiles
if (!file) {
wx.showToast({
title: '文件选择失败',
icon: 'none'
})
return
}
// 2. 读取文件
const fs = wx.getFileSystemManager()
fs.readFile({
filePath: file.path,
encoding: 'base64',
success: (readRes) => {
try {
// 3. 解析 Excel
const workbook = xlsx.read(readRes.data, { type: 'base64' })
const firstSheetName = workbook.SheetNames
const worksheet = workbook.Sheets
// 4. 转换为 JSON 数组(header: 1 表示第一行作为表头)
const jsonData = xlsx.utils.sheet_to_json(worksheet, {
header: 1,
defval: ''
})
if (!jsonData || jsonData.length < 2) {
wx.showToast({
title: 'Excel 文件格式不正确',
icon: 'none'
})
return
}
// 5. 解析表头
const headers = jsonData
const dateIndex = headers.indexOf('日期')
const moneyIndex = headers.indexOf('总资产(元)')
const uuidIndex = headers.indexOf('uuid')
if (dateIndex === -1 || moneyIndex === -1) {
wx.showToast({
title: 'Excel 文件缺少必要列',
icon: 'none'
})
return
}
// 6. 处理数据
const importedData = []
for (let i = 1; i < jsonData.length; i++) {
const row = jsonData
if (!row && !row) {
continue // 跳过空行
}
importedData.push({
date: row || '',
allmoney: row || '0',
uuid: row || String((new Date()).getTime() + i)
})
}
if (importedData.length === 0) {
wx.showToast({
title: '没有有效数据可导入',
icon: 'none'
})
return
}
// 7. 保存数据
const currentData = wx.getStorageSync("data") ? JSON.parse(wx.getStorageSync("data")) : []
const mergedData = [...currentData, ...importedData]
wx.setStorageSync("data", JSON.stringify(mergedData))
wx.showToast({
title: `成功导入 ${importedData.length} 条记录`,
icon: 'success'
})
} catch (error) {
console.error('导入 Excel 失败:', error)
wx.showToast({
title: '导入失败,请检查文件格式',
icon: 'none'
})
}
},
fail: (err) => {
console.error('读取文件失败:', err)
wx.showToast({
title: '读取文件失败',
icon: 'none'
})
}
})
},
fail: (err) => {
if (err.errMsg && err.errMsg.indexOf('cancel') === -1) {
wx.showToast({
title: '选择文件失败',
icon: 'none'
})
}
}
})
}
</pre></div>
<p class="maodian"><a name="_lab2_3_6"></a></p><h3>4.3 重复数据检测示例</h3>
<p>在导入时检测重复数据并提示用户:</p>
<div class="jb51code"><pre class="brush:js;">// 检查是否有重复数据(对比 uuid 字段)
const duplicateUuids = []
importedData.forEach(item => {
const itemUuid = String(item['uuid'] || '')
const existingIndex = currentData.findIndex((existing) =>
String(existing['uuid'] || '') === itemUuid
)
if (existingIndex >= 0) {
duplicateUuids.push(itemUuid)
}
})
// 如果有重复数据,提示用户
if (duplicateUuids.length > 0) {
wx.showModal({
title: '数据重复',
content: `检测到 ${duplicateUuids.length} 条重复数据,是否覆盖?`,
confirmText: '覆盖',
cancelText: '取消',
success: (modalRes) => {
if (modalRes.confirm) {
// 执行导入逻辑
doImport(importedData)
} else {
wx.showToast({
title: '已取消导入',
icon: 'none'
})
}
}
})
} else {
// 没有重复,直接导入
doImport(importedData)
}
</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>五、常用 API 说明</h2>
<p class="maodian"><a name="_lab2_4_7"></a></p><h3>5.1 核心方法</h3>
<table><thead><tr><th>方法</th><th>说明</th><th>示例</th></tr></thead><tbody><tr><td><code>xlsx.utils.aoa_to_sheet(data)</code></td><td>将二维数组转换为工作表</td><td><code>xlsx.utils.aoa_to_sheet([['A', 'B'], ])</code></td></tr><tr><td><code>xlsx.utils.book_new()</code></td><td>创建新工作簿</td><td><code>var wb = xlsx.utils.book_new()</code></td></tr><tr><td><code>xlsx.utils.book_append_sheet(wb, ws, name)</code></td><td>将工作表添加到工作簿</td><td><code>xlsx.utils.book_append_sheet(wb, ws, "Sheet1")</code></td></tr><tr><td><code>xlsx.write(wb, options)</code></td><td>将工作簿转换为指定格式</td><td><code>xlsx.write(wb, {bookType: "xlsx", type: 'base64'})</code></td></tr><tr><td><code>xlsx.read(data, options)</code></td><td>读取 Excel 文件</td><td><code>xlsx.read(base64Data, { type: 'base64' })</code></td></tr><tr><td><code>xlsx.utils.sheet_to_json(ws, options)</code></td><td>将工作表转换为 JSON</td><td><code>xlsx.utils.sheet_to_json(ws, { header: 1 })</code></td></tr></tbody></table>
<p class="maodian"><a name="_lab2_4_8"></a></p><h3>5.2 工作表属性设置</h3>
<p><strong>设置列宽:</strong></p>
<div class="jb51code"><pre class="brush:js;">ws['!cols'] = [
{ wch: 15 },// 第一列宽度:15个字符
{ wch: 20 },// 第二列宽度:20个字符
{ wch: 30 } // 第三列宽度:30个字符
]
</pre></div>
<p><strong>设置行高(可选):</strong></p>
<div class="jb51code"><pre class="brush:js;">ws['!rows'] = [
{ hpt: 20 },// 第一行高度:20磅
{ hpt: 15 } // 第二行高度:15磅
]
</pre></div>
<p class="maodian"><a name="_lab2_4_9"></a></p><h3>5.3 xlsx.write() 选项</h3>
<div class="jb51code"><pre class="brush:js;">xlsx.write(wb, {
bookType: "xlsx",// 文件类型:xlsx, xls, csv 等
type: 'base64', // 输出类型:base64, binary, string, buffer
bookSST: true // 是否使用共享字符串表(可选)
})
</pre></div>
<p class="maodian"><a name="_lab2_4_10"></a></p><h3>5.4 sheet_to_json() 选项</h3>
<div class="jb51code"><pre class="brush:js;">xlsx.utils.sheet_to_json(worksheet, {
header: 1, // 1: 数组格式,'A': 对象格式(使用列名)
defval: '', // 默认值(空单元格的值)
raw: false // false: 自动转换数据类型,true: 保持原始值
})
</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>六、注意事项</h2>
<ol><li><p><strong>文件大小限制</strong>:微信小程序对文件大小有限制,建议单个 Excel 文件不超过 2MB</p></li><li><p><strong>数据类型</strong>:导入时注意数据类型转换,Excel 中的数字可能被解析为字符串</p></li><li><p><strong>空值处理</strong>:使用 <code>defval</code> 参数设置空单元格的默认值</p></li><li><p><strong>错误处理</strong>:务必添加 try-catch 错误处理,避免程序崩溃</p></li><li><p><strong>平台差异</strong>:PC 端和手机端的文件保存方式不同,需要分别处理</p></li><li><p><strong>文件路径</strong>:使用 <code>wx.env.USER_DATA_PATH</code> 获取用户数据目录</p></li><li><p><strong>列宽单位</strong>:<code>wch</code> 表示字符宽度,不是像素</p></li><li><p><strong>工作表名称</strong>:工作表名称不能包含特殊字符,建议使用中文、英文、数字</p></li></ol>
<p>希望本文能帮助你在微信小程序项目中顺利实现 Excel 导入导出功能!</p>
<p><strong>参考资源:</strong></p>
<ul><li>SheetJS 官方文档:https://docs.sheetjs.com/</li><li>SheetJS GitHub:https://github.com/SheetJS/sheetjs</li></ul>
頁:
[1]