Node.js使用xlsx库读取Excel并处理合并单元格

作者:星河时间:2026-10-31 19:50:23浏览:408

本文介绍如何在Node.js环境中使用xlsx库读取Excel文件,重点解决合并单元格数据的正确获取问题。通过解析合并区域信息,实现从特定工作表提取表头及结构化数据,并将结果转换为JSON格式输出。

在当前的数据处理场景中,Excel 文件作为广泛使用的数据存储格式,广泛应用于数据分析、报表生成和数据迁移等环节。然而,面对包含合并单元格的 Excel 文件时,数据的提取和处理往往面临一定难度。本文将详细阐述如何利用 Node.js 技术读取 Excel 文件,并有效处理其中的合并单元格问题。

准备工作

准备工作

首先,需要安装 Node.js 所需的依赖库。本文选用 xlsx 库负责 Excel 文件的读取与解析,同时使用 lodash 库辅助字符串处理。可通过执行以下命令完成库的安装:

npm install xlsx lodash

读取 Excel 文件

第一步是读取目标 Excel 文件。假设文件名为 YD-TP2025-03-22.xlsx,且存放于项目根目录。利用 xlsx.readFile 方法即可实现文件读取:

const xlsx = require('xlsx');
const path = require('path');

​​​​​​​const filePath = path.join(__dirname, 'YD-TP2025-03-22.xlsx');
const workbook = xlsx.readFile(filePath);

获取工作表

随后,需从 Excel 文件中提取指定的工作表。假设目标工作表名称为“建设全流程明细”,可通过如下代码获取该工作表对象:

const sheetName = "建设全流程明细";
const sheet = workbook.Sheets[sheetName];

处理合并单元格

Excel 文件中的合并单元格处理是常见难点。通常,合并区域的值仅保留在左上角单元格,其余单元格值为空。为准确获取数据,需先获取合并单元格的相关信息,并据此推导正确的单元格值。

可通过以下代码获取工作表中的合并单元格配置信息:

const merges = sheet['!merges'] || [];

接着,定义一个名为 getMergedCellValue 的函数,用于根据行列坐标获取合并单元格的实际值:

function getMergedCellValue(sheet, row, col) {
    for (const merge of merges) {
        const { s, e } = merge; // s: 合并区域的起始位置,e: 合并区域的结束位置
        if (row >= s.r && row <= e.r && col >= s.c && col <= e.c) {
            return sheet[xlsx.utils.encode_cell(s)]?.v;
        }
    }
    return sheet[xlsx.utils.encode_cell({ r: row, c: col })]?.v;
}

获取表头数据

假设表头数据位于 Excel 的第 4 行,可通过以下代码提取表头信息:

const headerTemplates = [];
const rowIndex = 3; // 第 4 行的索引(从 0 开始)
const range = xlsx.utils.decode_range(sheet['!ref']);

for (let col = range.s.c; col <= range.e.c; col++) {
    const cellValue = getMergedCellValue(sheet, rowIndex, col);
    if (cellValue) {
        const address = xlsx.utils.encode_cell({ r: rowIndex, c: col }) + '';
        headerTemplates.push({
            address: address,
            value: removeTabsAndNewlines(cellValue),
            col: col + 1  // Excel 列从 1 开始计数
        });
    }
}

输出表头模板数据

最后,将提取到的表头数据以 JSON 格式进行输出:

console.log(JSON.stringify(headerTemplates, null, 2));
[Running] node "c:\Users\xiong\WebstormProjects\backendnodejs\src\models\scripts\tempCodeRunnerFile.js"
[
  {
    "address": "A4",
    "value": "序号",
    "col": 1
  },
  {
    "address": "B4",
    "value": "区县",
    "col": 2
  },
  {
    "address": "C4",
    "value": "线下收到需求时间(以邮件为准等书面通知为准)",
    "col": 3
  },
  {
    "address": "D4",
    "value": "订单编号",
    "col": 4
  },
  {
    "address": "E4",
    "value": "未进系统原因",
    "col": 5
  },
  {
    "address": "F4",
    "value": "年份",
    "col": 6
  },
  {
    "address": "G4",
    "value": "运营商",
    "col": 7
  },

将数据转换为结构化 JSON

从第 5 行(即索引为 4 的行)开始遍历数据,将每一行数据转换为对象。对象的键对应表头字段,值对应单元格内容。最终将所有数据存入数组中:

const xlsx = require('xlsx');
const path = require('path');

// 读取 Excel 文件
const filePath = path.join(__dirname, 'YD-TP2025-03-22.xlsx');
const workbook = xlsx.readFile(filePath);

// 获取名为 "建设全流程明细" 的工作表
const sheetName = "建设全流程明细";
const sheet = workbook.Sheets[sheetName];

// 获取工作表的合并单元格信息
const merges = sheet['!merges'] || [];

// 定义一个函数,用于获取合并单元格的值
function getMergedCellValue(sheet, row, col) {
    for (const merge of merges) {
        const { s, e } = merge;
        if (row >= s.r && row <= e.r && col >= s.c && col <= e.c) {
            return sheet[xlsx.utils.encode_cell(s)]?.v;
        }
    }
    return sheet[xlsx.utils.encode_cell({ r: row, c: col })]?.v;
}

// 获取表头数据(第 4 行)
const headerRow = [];
const headerRowIndex = 3; // 第 4 行的索引(从 0 开始)
const range = xlsx.utils.decode_range(sheet['!ref']);

// 获取表头
for (let col = range.s.c; col <= range.e.c; col++) {
    const cellValue = getMergedCellValue(sheet, headerRowIndex, col);
    headerRow.push(cellValue || '');
}

// 将数据转换为列表
const dataList = [];

// 从第5行开始读取数据(索引4)
for (let row = headerRowIndex + 1; row <= range.e.r; row++) {
    const rowData = {};
    
    // 遍历每一列
    for (let col = range.s.c; col <= range.e.c; col++) {
        const cellValue = getMergedCellValue(sheet, row, col);
        // 使用表头作为键名
        rowData[headerRow[col]] = cellValue || '';
    }
    
    dataList.push(rowData);
}

// 输出前5条数据作为示例
console.log('数据总条数:', dataList.length);
console.log('前5条数据示例:');
console.log(JSON.stringify(dataList.slice(5, 25), null, 2)); 

[Running] node "c:\Users\xiong\WebstormProjects\backendnodejs\src\models\scripts\excel_tolist.js" 数据总条数: 9 前5条数据示例: [ { "序号": 5, "区县": "长沙县", "线下收到需求时间\n(以邮件为准等书面通知为准)": 45523, "订单编号": "新建选址", "未进系统原因": "新建选址完成后进系统", "年份": "2024年", "运营商": "移动", "项目归属": "岳麓山景区", "运营商批次": "普通5G", "重点项目打标": "", "需求站址名称": "长沙岳麓岳麓山东门路口微站H-H5X", "铁塔站址名称": "", "铁塔站址编码": "", "项目编码/存量满足": "", "立项方式(存量满足常规塔类/区域化塔类/非标改造)": "微站", "运营商建设方式(新址新建、共址新建、共址改造)": "新址新建", "铁塔建设方式(新建、改造、存满)": "新建", "产品单元数": 1, "建设类型(地面站,楼面站)": "地面站", "建设方案\n(含所有建设工程量)": "利旧电力路灯杆,新增光电一体箱,新增支臂,外市电", "打标": "2、地面新建", "订单导入时间": "", ............

总结

通过上述步骤,我们成功利用 Node.js 读取了 Excel 文件,并解决了合并单元格数据的处理问题。该方法不仅适用于表头数据的提取,也可应用于其他复杂 Excel 数据的处理场景。

关于 Node.js 读取 Excel 文件并处理合并单元格的介绍到此结束。如需了解更多 Node.js 读取 Excel 的相关内容,建议查阅本站往期文章或继续浏览后续内容。感谢支持!

作者最新文章