vue excel转json功能 xlsx

在这里插入图片描述

需求:

  1. 完成excel表格内容转json,excel表格内可能存在多个表格,要求全部解析出来。
  2. 完成表格内合服功能,即:提取表格内老服务器与新服务器数据,多台老服务器对应合并到一台新服务器上
    3.最终输出结果为:[{‘10086-l’:[‘10086-1’,‘10086-2’,…]}] …

一、前置准备

安装依赖

首先确保安装 xlsx 库:

npm install xlsx
核心思路

嵌套表格通常通过空行、固定标题或特定标识分隔,且子表格结构一致(如列数、表头相同)。需通过遍历行数据,识别子表格的边界(起始行、结束行),再提取每个子表格的内容并转换为 JSON。

二、实现步骤及代码

假设 Excel 结构如下(示例):
包含 3 个子表格,以空行分隔,每个子表格有表头(name、id、老服务器,新服务器)和数据行。

1. 读取 Excel 文件并解析工作表
return new Promise((resolve, reject) => {
        const reader = new FileReader();
        // 开始读取文件内容
        reader.readAsArrayBuffer(raw);
        reader.onload = (e) => {
        
                // 将文件内容读取为ArrayBuffer并解析为workbook对象
                const data = e.target?.result;
                // 第一行开始 第五行结束
                const workbook = XLSX.read(data, { type: "array" });

                // 获取第一个工作表数据并转换为JSON格式
                const sheetName = workbook.SheetNames[0];
                const worksheet = workbook.Sheets[sheetName];

                const rows = XLSX.utils.sheet_to_json(worksheet, {
                    header: 1,
                    raw: false, // 保留原始值(字符串)
                });
        };
        // 处理文件读取错误
        reader.onerror = (error) => {
            reject(error);
        };
    });
2. 识别子表格边界

通过空行(元素全为 undefined 或空字符串)分隔子表格,记录每个子表格的起始行和结束行:

// 存储所有子表格的范围:{ start: 行索引, end: 行索引 }
const tableRanges = [];
let currentStart = null;

// 遍历所有行,识别子表格边界
for (let i = 0; i < rows.length; i++) {
  const row = rows[i];
  // 判断是否为空行(过滤全空或仅含空字符串的行)
  const isEmptyRow = row.every(cell => cell === undefined || cell === null || cell === '');

  if (!isEmptyRow) {
    // 非空行:若未记录起始行,则标记为子表格开始
    if (currentStart === null) {
      currentStart = i;
    }
  } else {
    // 空行:若已记录起始行,则标记为子表格结束
    if (currentStart !== null) {
      tableRanges.push({ start: currentStart, end: i - 1 });
      currentStart = null;
    }
  }
}

// 处理最后一个子表格(若文件末尾无空行)
if (currentStart !== null) {
  tableRanges.push({ start: currentStart, end: rows.length - 1 });
}
3. 提取子表格数据并转换为 JSON

假设每个子表格的第一行为表头,后续为数据行:

// 存储最终结果:键为子表格索引,值为数据数组
 // 存储最终结果:键为子表格索引,值为数据数组
    const result = [];

    tableRanges.forEach((range, tableIndex) => {
        const { start, end } = range;
        // 表头行(子表格起始行)
        const headers = rows[start].filter(cell => cell !== undefined && cell !== ''); // 过滤空单元格
        // 数据行(从表头下一行到结束行)
        const tableData = [];

        for (let i = start + 1; i <= end; i++) {
            const row = rows[i];
            const rowData = {};
            // 映射表头与数据(忽略超出表头列数的单元格)
            headers.forEach((header, colIndex) => {
                rowData[header] = row[colIndex] || ''; // 空单元格用空字符串代替
            });
            tableData.push(rowData);
        }
        tableData.forEach(rowData => {
            if (rowData.newServer) {

            }
        });
        let data = transformServers(tableData)
        if (Object.keys(data).length) {
            result.push(data)
        }

    });

三、关键处理说明

1. 边界识别优化

若子表格通过特定标题(如 “表格 1 开始”)分隔,可修改空行判断逻辑,例如:

// 假设子表格以 "表格x" 开头
const isTableHeader = row[0]?.startsWith('表格');
if (isTableHeader) { /* 标记子表格开始 */ }
  1. 合并单元格处理
    若存在合并单元格,xlsx 会仅在合并区域的首个单元格保留值,其他为 undefined。可通过以下方式填充合并单元格数据:
// 先获取合并单元格信息
const merges = worksheet['!merges'] || [];
// 遍历合并区域,复制首个单元格的值到其他位置
merges.forEach(merge => {
  const { s, e } = merge; // s: 起始行/列, e: 结束行/列
  const value = rows[s.r][s.c];
  for (let r = s.r; r <= e.r; r++) {
    for (let c = s.c; c <= e.c; c++) {
      rows[r][c] = value;
    }
  }
});

数据类型转换

默认输出为字符串,可根据需求自行格式化

function transformServers(servers) {
    const result = {};
    let currentNewServer = null;
    let keys = Object.keys(servers[0]);
    for (const serverInfo of servers) {
        // 如果当前项有newServer值,更新当前newServer
        if (serverInfo[keys[3]]) {
            currentNewServer = serverInfo[keys[3]];
            // 初始化数组并添加当前server
            result[currentNewServer] = [serverInfo[keys[2]]];
        }
        // 如果当前有活跃的newServer且当前项没有newServer,添加到数组
        else if (currentNewServer) {
            result[currentNewServer].push(serverInfo[keys[2]]);
        }
    }

    return result;
}

四、页面代码部分

<template>
<el-dialog
  title="提示"
  :visible.sync="dialogVisible"
  width="500"
  :before-close="handleClose">
    <el-upload
        class="upload-demo"
        drag
        action="''"
        :multiple="false"
        :auto-upload="false"
        :file-list="fileList"
        :on-change="handleChange"
        :on-remove="beforeUpload"
        ref="upload"
  :limit="1"
        accept=".xlsx,.xls"
        >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
            <div>将文件拖到此处,或<em>点击上传</em></div>
            <div class="el-upload__tip">
              上传excel文件,请勿超过5M,每次最多只能上传1个文件
            </div>
        </div>
        </el-upload>
  <span slot="footer" class="dialog-footer">
    <el-button type="primary" @click="toJson">tojson</el-button>
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span>
</el-dialog>
</template>
<script>
  import {excelToJson} from '../../../utils/excel2json'
  export default {
    data() {
      return {
        dialogVisible: false,
        fileList: [],
      };
    },
    methods: { 
        handleChange(file, fileList){
          console.log(fileList,file,'---');
          
            this.fileList = fileList; 
        },
        beforeUpload(file,fileList){
          console.log(fileList,'--');
          this.fileList = fileList; 
        },
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
      toJson(){
        console.log(this.fileList);
        
        excelToJson(this.fileList[0].raw)
      }
    },
  
  };
</script>
<style lang="scss">
.upload-demo{
.el-upload {
  width:100%;
}
.el-upload-dragger{
  width:100%;
}
    width:100%;
}
</style>
五、总结

通过上述步骤,可实现对嵌套规律表格的解析:

读取 Excel 并转换为行数组;
根据空行或特定标识识别子表格范围;
提取每个子表格的表头和数据,映射为 JSON 对象;
按需处理合并单元格和数据类型。
根据实际 Excel 结构,只需调整边界识别逻辑和表头映射规则即可适配不同场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值