Vue项目中使用xlsx库解析Excel文件
2026年1月16日 15:34
项目中有个需求是上传Excel实现批量导入,但是解析Excel的需要前端来实现,所以用到了xlsx库
xlsx 库是一个强大的 JavaScript 库,用于处理 Excel 文件,支持:
- 读取
.xls和.xlsx格式 - 写入 Excel 文件
- 解析工作表数据
- 支持多种数据格式转换
在项目中安装 xlsx 库:
npm install xlsx
# 或者使用 yarn
yarn add xlsx
# 或者使用 pnpm
pnpm add xlsx
核心 API
import * as XLSX from 'xlsx';
// 主要方法
XLSX.read(data, options) // 读取 Excel 数据
XLSX.readFile(filename) // 从文件读取
XLSX.utils.sheet_to_json() // 工作表转 JSON
XLSX.utils.sheet_to_csv() // 工作表转 CSV
XLSX.utils.sheet_to_html() // 工作表转 HTML
Excel 文件读取与解析
1. 使用 FileReader 读取文件
在浏览器环境中,我们需要使用 FileReader API 来读取用户上传的文件:
const readExcelFile = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
// 读取文件内容
const data = new Uint8Array(e.target.result);
resolve(data);
} catch (error) {
reject(new Error('文件读取失败'));
}
};
reader.onerror = () => {
reject(new Error('文件读取失败'));
};
// 以 ArrayBuffer 格式读取文件
reader.readAsArrayBuffer(file);
});
};
2. 解析 Excel 文件
使用 XLSX.read() 方法解析 Excel 数据:
const parseExcelData = (data) => {
// 读取 Excel 工作簿
const workbook = XLSX.read(data, { type: 'array' });
// 获取所有工作表名称
const sheetNames = workbook.SheetNames;
console.log('工作表名称:', sheetNames);
// 获取第一个工作表
const firstSheetName = sheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 将工作表转换为 JSON
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
return {
workbook,
worksheet,
jsonData,
sheetNames
};
};
3. 不同数据格式的转换
// 转换为 JSON 对象(带表头)
const jsonWithHeaders = XLSX.utils.sheet_to_json(worksheet);
// 转换为 JSON 数组(不带表头)
const jsonArray = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
// 转换为 CSV 字符串
const csvString = XLSX.utils.sheet_to_csv(worksheet);
// 转换为 HTML 表格
const htmlString = XLSX.utils.sheet_to_html(worksheet);
表头验证与数据提取
1. 验证表头格式
在实际应用中,我们通常需要验证 Excel 文件的表头是否符合预期格式:
const validateExcelHeaders = (jsonData, requiredHeaders) => {
if (jsonData.length === 0) {
throw new Error('Excel文件为空');
}
// 获取表头行(第一行)
const headers = jsonData[0].map(header =>
header ? header.toString().trim() : ''
);
// 检查必需表头
const missingHeaders = requiredHeaders.filter(header =>
!headers.includes(header)
);
if (missingHeaders.length > 0) {
throw new Error(`缺少必需表头: ${missingHeaders.join(', ')}`);
}
return headers;
};
2. 提取数据行
const extractDataRows = (jsonData, headers) => {
// 跳过表头行(第一行)
const dataRows = jsonData.slice(1);
return dataRows.map((row, rowIndex) => {
const rowData = {};
headers.forEach((header, colIndex) => {
rowData[header] = row[colIndex] || '';
});
return {
...rowData,
_rowNumber: rowIndex + 2 // Excel 行号(从1开始,表头为第1行)
};
}).filter(row => {
// 过滤空行(所有单元格都为空)
return Object.values(row).some(value =>
value !== '' && value !== undefined && value !== null
);
});
};
3. 数据验证与清洗
const validateAndCleanData = (dataRows, validationRules) => {
const errors = [];
const cleanedData = [];
dataRows.forEach((row, index) => {
const rowErrors = [];
// 检查每个字段
Object.keys(validationRules).forEach(field => {
const value = row[field];
const rules = validationRules[field];
// 必填验证
if (rules.required && (!value || value.toString().trim() === '')) {
rowErrors.push(`${field} 不能为空`);
}
// 类型验证
if (value && rules.type) {
if (rules.type === 'number' && isNaN(Number(value))) {
rowErrors.push(`${field} 必须是数字`);
}
if (rules.type === 'email' && !isValidEmail(value)) {
rowErrors.push(`${field} 格式不正确`);
}
}
// 枚举值验证
if (value && rules.enum && !rules.enum.includes(value)) {
rowErrors.push(`${field} 必须是以下值之一: ${rules.enum.join(', ')}`);
}
});
if (rowErrors.length === 0) {
cleanedData.push(row);
} else {
errors.push({
row: row._rowNumber,
errors: rowErrors
});
}
});
return { cleanedData, errors };
};