Vue项目中使用xlsx库解析Excel文件

项目中有个需求是上传Excel实现批量导入,但是解析Excel的需要前端来实现,所以用到了xlsx库

xlsx 库是一个强大的 JavaScript 库,用于处理 Excel 文件,支持:

  • 读取 .xls.xlsx 格式
  • 写入 Excel 文件
  • 解析工作表数据
  • 支持多种数据格式转换

在项目中安装 xlsx 库:

bash 复制代码
npm install xlsx
# 或者使用 yarn
yarn add xlsx
# 或者使用 pnpm
pnpm add xlsx

核心 API

javascript 复制代码
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 来读取用户上传的文件:

javascript 复制代码
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 数据:

javascript 复制代码
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. 不同数据格式的转换

javascript 复制代码
// 转换为 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 文件的表头是否符合预期格式:

javascript 复制代码
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. 提取数据行

javascript 复制代码
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. 数据验证与清洗

javascript 复制代码
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 };
};
相关推荐
一只小阿乐2 小时前
vue 改变查询参数的值
前端·javascript·vue.js·路由·router·网文·未花中文网
小酒星小杜2 小时前
在AI时代下,技术人应该学会构建自己的反Demo地狱系统
前端·vue.js·ai编程
Code知行合壹3 小时前
Pinia入门
vue.js
今天也要晒太阳4733 小时前
element表单和vxe表单联动校验的实现
vue.js
依赖_赖4 小时前
前端实现token无感刷新
前端·javascript·vue.js
hhcccchh5 小时前
学习vue第十三天 Vue3组件深入指南:组件的艺术与科学
javascript·vue.js·学习
zhengxianyi5155 小时前
ruoyi-vue-pro本地环境搭建(超级详细,带异常处理)
前端·vue.js·前后端分离·ruoyi-vue-pro
绝美焦栖5 小时前
低版本pdfjs升级
前端·javascript·vue.js
卤蛋fg66 小时前
vue 可视化表单设计器 vxe-form-design 创建自定义控件的详细用法(教程一)
vue.js