使用 Node.js 读取 Excel 文件并处理合并单元格

使用 Node.js 读取 Excel 文件并处理合并单元格

在现代的数据处理任务中,Excel 文件是一种非常常见的数据存储格式。无论是数据分析、报表生成,还是数据迁移,Excel 文件都扮演着重要的角色。然而,处理 Excel 文件时,尤其是包含合并单元格的文件,可能会遇到一些挑战。本文将介绍如何使用 Node.js 读取 Excel 文件,并处理其中的合并单元格。

准备工作

首先,我们需要安装一些必要的 Node.js 库。我们将使用 xlsx 库来读取和解析 Excel 文件,使用 lodash 库来处理字符串。你可以通过以下命令安装这些库:

bash 复制代码
npm install xlsx lodash

读取 Excel 文件

我们首先需要读取 Excel 文件。假设我们的文件名为 YD-TP2025-03-22.xlsx,并且它位于当前项目的根目录下。我们可以使用 xlsx.readFile 方法来读取文件:

javascript 复制代码
const xlsx = require('xlsx');
const path = require('path');

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

获取工作表

接下来,我们需要获取 Excel 文件中的特定工作表。假设我们的工作表名为 建设全流程明细,我们可以通过以下代码获取该工作表:

javascript 复制代码
const sheetName = "建设全流程明细";
const sheet = workbook.Sheets[sheetName];

处理合并单元格

在处理 Excel 文件时,合并单元格是一个常见的挑战。合并单元格的值通常只存储在合并区域的左上角单元格中,其他单元格的值为空。为了正确处理合并单元格,我们需要获取合并单元格的信息,并根据这些信息来获取正确的值。

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

javascript 复制代码
const merges = sheet['!merges'] || [];

然后,我们定义一个函数 getMergedCellValue,用于获取合并单元格的值:

javascript 复制代码
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;
}

获取表头数据

假设我们的表头数据位于第 4 行,我们可以通过以下代码获取表头数据:

javascript 复制代码
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 格式:

javascript 复制代码
console.log(JSON.stringify(headerTemplates, null, 2));
bash 复制代码
[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)开始读取数据,并将每一行数据转换为一个对象,其中键为表头字段,值为单元格内容。最后,将所有数据存储在一个数组中

javascript 复制代码
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)); 
javascript 复制代码
[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 数据。希望这篇文章能帮助你在处理 Excel 文件时更加得心应手。

如果你有任何问题或建议,欢迎在评论区留言!

相关推荐
red润7 小时前
npm包autocannon牛逼的后台压力测试库
前端·javascript·node.js
Ethan_Zhou【数据恢复专家】7 小时前
Node.js 性能提升秘籍:多线程与 HTTP 并发管理策略
网络协议·http·node.js
程序员差不多先生11 小时前
如何在阿里云linux主机上部署Node.Js
阿里云·node.js
Smilecoc11 小时前
EXCEL报错:无法共享此工作薄,因表包含excel表或xml映射的解决方法
xml·excel
hahala233312 小时前
MCP 入门实践
node.js
星尘安全14 小时前
恶意npm包修改本地“以太坊”库以发起反弹Shell攻击
前端·npm·node.js·供应链安全·黑客攻击
还是鼠鼠16 小时前
Node.js 如何发布一个 NPM 包——详细教程
前端·vscode·npm·node.js
我是六月生1 天前
右击没有Word、PPT、Excel功能
word·powerpoint·excel
杜子腾dd1 天前
4.用 Excel 录入数据
excel
有人说风轻的像雨1 天前
使用 Node.js 和 163 邮箱发送邮件
node.js