当前位置: 首页 > news >正文

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

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

在现代的数据处理任务中,Excel 文件是一种非常常见的数据存储格式。无论是数据分析、报表生成,还是数据迁移,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;
}

获取表头数据

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

总结

通过以上步骤,我们成功地使用 Node.js 读取了 Excel 文件,并处理了其中的合并单元格。这种方法不仅适用于获取表头数据,还可以用于处理其他复杂的 Excel 数据。希望这篇文章能帮助你在处理 Excel 文件时更加得心应手。

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

相关文章:

  • Spring:AOP
  • 网络HTTPS协议
  • SOFABoot-08-启动加速
  • 修改服务器windows远程桌面默认端口号
  • 苹果iPhone屏幕防护专利获批,未来iPhone或更耐用
  • Linux 通过压缩包安装 MySQL 并设置远程连接教程
  • Nginx及前端部署全流程:初始化配置到生产环境部署(附Nginx常用命令)
  • I/O 多路复用(I/O Multiplexing)
  • Java面试黄金宝典9
  • Linux | ubuntu安装 SSH 软件及测试工具
  • 挂谷猜想的证明错误百出
  • 嵌入式基础知识学习:SPI通信协议是什么?
  • 【趣谈】了解语音拼写检查算法的内部机制
  • PTA团体程序设计天梯赛-练习集71-75题
  • 2025年渗透测试面试题总结-某深信服 -安全工程师(题目+回答)
  • 关于转嵌入式的一点想法
  • 不做颠覆者,甘为连接器,在技术叠层中培育智能新物种
  • 蓝桥杯(N皇后问题)------回溯法
  • C语言:循环控制结构习题
  • 【C语言】深入理解指针(二):从数组到二维数组的指针魔法
  • 股价两天涨超30%,中航成飞:不存在应披露而未披露的重大事项
  • 以军总参谋长:已进入“决定性打击计划的第二阶段”
  • 上海充电桩调研:须全盘考量、分步实现车网互动规模化
  • 明天起,沪苏湖高铁、杭温高铁推出13款新型票制产品
  • 上海:下调个人住房公积金贷款利率
  • 马上评|演出服“穿过就退货”的闹剧不该一再重演