使用 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 文件时更加得心应手。

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

相关推荐
weixin_472339462 小时前
python批量解析提取word内容到excel
python·word·excel
IT瘾君14 小时前
JavaWeb:前端工程化-ElementPlus
前端·elementui·node.js·vue
早知道不学Java了15 小时前
chromedriver 下载失败
前端·vue.js·react.js·npm·node.js
15 小时前
Unity与Excel表格交互热更方案
unity·游戏引擎·excel
金融小白数据分析之路17 小时前
Excel高级函数使用FILTER、UNIQUE、INDEX
excel
未来之窗软件服务17 小时前
Excel表格批量下载 CyberWin Excel Doenlaoder 智能编程-——玄武芯辰
excel·批量下载·仙盟创梦ide·东方仙盟
贩卖纯净水.17 小时前
Webpack搭建本地服务器
前端·webpack·node.js
树獭叔叔17 小时前
从零开始Node之旅 —— 事件模型
后端·node.js
xd0000217 小时前
3. 简述node.js特性与底层原理
node.js
盼儿哥18 小时前
123网盘SDK-npm包已发布
前端·npm·node.js