Node.js讀取Excel文件并處理合并單元格
在現(xiàn)代的數(shù)據(jù)處理任務(wù)中,Excel 文件是一種非常常見的數(shù)據(jù)存儲(chǔ)格式。無論是數(shù)據(jù)分析、報(bào)表生成,還是數(shù)據(jù)遷移,Excel 文件都扮演著重要的角色。然而,處理 Excel 文件時(shí),尤其是包含合并單元格的文件,可能會(huì)遇到一些挑戰(zhàn)。本文將介紹如何使用 Node.js 讀取 Excel 文件,并處理其中的合并單元格。
準(zhǔn)備工作
首先,我們需要安裝一些必要的 Node.js 庫。我們將使用 xlsx 庫來讀取和解析 Excel 文件,使用 lodash 庫來處理字符串。你可以通過以下命令安裝這些庫:
npm install xlsx lodash
讀取 Excel 文件
我們首先需要讀取 Excel 文件。假設(shè)我們的文件名為 YD-TP2025-03-22.xlsx,并且它位于當(dāng)前項(xiàng)目的根目錄下。我們可以使用 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 文件中的特定工作表。假設(shè)我們的工作表名為 建設(shè)全流程明細(xì),我們可以通過以下代碼獲取該工作表:
const sheetName = "建設(shè)全流程明細(xì)"; const sheet = workbook.Sheets[sheetName];
處理合并單元格
在處理 Excel 文件時(shí),合并單元格是一個(gè)常見的挑戰(zhàn)。合并單元格的值通常只存儲(chǔ)在合并區(qū)域的左上角單元格中,其他單元格的值為空。為了正確處理合并單元格,我們需要獲取合并單元格的信息,并根據(jù)這些信息來獲取正確的值。
我們可以通過以下代碼獲取工作表的合并單元格信息:
const merges = sheet['!merges'] || [];
然后,我們定義一個(gè)函數(shù) getMergedCellValue,用于獲取合并單元格的值:
function getMergedCellValue(sheet, row, col) { for (const merge of merges) { const { s, e } = merge; // s: 合并區(qū)域的起始位置,e: 合并區(qū)域的結(jié)束位置 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; }
獲取表頭數(shù)據(jù)
假設(shè)我們的表頭數(shù)據(jù)位于第 4 行,我們可以通過以下代碼獲取表頭數(shù)據(jù):
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 開始計(jì)數(shù) }); } }
輸出表頭模板數(shù)據(jù)
最后,我們可以將獲取到的表頭數(shù)據(jù)輸出為 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": "區(qū)縣", "col": 2 }, { "address": "C4", "value": "線下收到需求時(shí)間(以郵件為準(zhǔn)等書面通知為準(zhǔn))", "col": 3 }, { "address": "D4", "value": "訂單編號", "col": 4 }, { "address": "E4", "value": "未進(jìn)系統(tǒng)原因", "col": 5 }, { "address": "F4", "value": "年份", "col": 6 }, { "address": "G4", "value": "運(yùn)營商", "col": 7 },
將數(shù)據(jù)轉(zhuǎn)換為結(jié)構(gòu)化 JSON
接下來,我們從第 5 行(索引為 4)開始讀取數(shù)據(jù),并將每一行數(shù)據(jù)轉(zhuǎn)換為一個(gè)對象,其中鍵為表頭字段,值為單元格內(nèi)容。最后,將所有數(shù)據(jù)存儲(chǔ)在一個(gè)數(shù)組中
const xlsx = require('xlsx'); const path = require('path'); // 讀取 Excel 文件 const filePath = path.join(__dirname, 'YD-TP2025-03-22.xlsx'); const workbook = xlsx.readFile(filePath); // 獲取名為 "建設(shè)全流程明細(xì)" 的工作表 const sheetName = "建設(shè)全流程明細(xì)"; const sheet = workbook.Sheets[sheetName]; // 獲取工作表的合并單元格信息 const merges = sheet['!merges'] || []; // 定義一個(gè)函數(shù),用于獲取合并單元格的值 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; } // 獲取表頭數(shù)據(jù)(第 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 || ''); } // 將數(shù)據(jù)轉(zhuǎn)換為列表 const dataList = []; // 從第5行開始讀取數(shù)據(jù)(索引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條數(shù)據(jù)作為示例 console.log('數(shù)據(jù)總條數(shù):', dataList.length); console.log('前5條數(shù)據(jù)示例:'); console.log(JSON.stringify(dataList.slice(5, 25), null, 2));
[Running] node "c:\Users\xiong\WebstormProjects\backendnodejs\src\models\scripts\excel_tolist.js"
數(shù)據(jù)總條數(shù): 9
前5條數(shù)據(jù)示例:
[
{
"序號": 5,
"區(qū)縣": "長沙縣",
"線下收到需求時(shí)間\n(以郵件為準(zhǔn)等書面通知為準(zhǔn))": 45523,
"訂單編號": "新建選址",
"未進(jìn)系統(tǒng)原因": "新建選址完成后進(jìn)系統(tǒng)",
"年份": "2024年",
"運(yùn)營商": "移動(dòng)",
"項(xiàng)目歸屬": "岳麓山景區(qū)",
"運(yùn)營商批次": "普通5G",
"重點(diǎn)項(xiàng)目打標(biāo)": "",
"需求站址名稱": "長沙岳麓岳麓山東門路口微站H-H5X",
"鐵塔站址名稱": "",
"鐵塔站址編碼": "",
"項(xiàng)目編碼/存量滿足": "",
"立項(xiàng)方式(存量滿足常規(guī)塔類/區(qū)域化塔類/非標(biāo)改造)": "微站",
"運(yùn)營商建設(shè)方式(新址新建、共址新建、共址改造)": "新址新建",
"鐵塔建設(shè)方式(新建、改造、存滿)": "新建",
"產(chǎn)品單元數(shù)": 1,
"建設(shè)類型(地面站,樓面站)": "地面站",
"建設(shè)方案\n(含所有建設(shè)工程量)": "利舊電力路燈桿,新增光電一體箱,新增支臂,外市電",
"打標(biāo)": "2、地面新建",
"訂單導(dǎo)入時(shí)間": "",
............
總結(jié)
通過以上步驟,我們成功地使用 Node.js 讀取了 Excel 文件,并處理了其中的合并單元格。這種方法不僅適用于獲取表頭數(shù)據(jù),還可以用于處理其他復(fù)雜的 Excel 數(shù)據(jù)。
到此這篇關(guān)于Node.js讀取Excel文件并處理合并單元格的文章就介紹到這了,更多相關(guān)Node.js讀取Excel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于node使用multer進(jìn)行文件的上傳與下載
這篇文章主要介紹了關(guān)于node使用multer進(jìn)行文件的上傳與下載,Multer是一個(gè)Node.js中間件,用于處理表單數(shù)據(jù)中的multipart/form-data類型,需要的朋友可以參考下2023-04-04Node.js + Redis Sorted Set實(shí)現(xiàn)任務(wù)隊(duì)列
本文給大家分享的是使用Node.js + Redis Sorted Set實(shí)現(xiàn)任務(wù)隊(duì)列的方法示例,非常的實(shí)用,有需要的小伙伴可以參考下2016-09-09Node.js?使用?zlib?內(nèi)置模塊進(jìn)行?gzip?壓縮
這篇文章主要介紹了Node.js?使用?zlib?內(nèi)置模塊進(jìn)行?gzip?壓縮,nodejs為我們提供了一個(gè)zlib內(nèi)置模塊,我們可以使用它其中的gzip方法來對傳遞的數(shù)據(jù)進(jìn)行壓縮,從而提高數(shù)據(jù)傳遞效率,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-09-09Node.js利用debug模塊打印出調(diào)試日志的方法
debug日志打印模塊主要實(shí)現(xiàn)功能是帶命名空間(模塊名)、時(shí)間戳、色彩輸出日志;將日志寫入文件;瀏覽器端使用;格式化函數(shù);支持自定義方法。下面這篇文章主要介紹了Node.js利用debug模塊打印出調(diào)試日志的方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-04-04PHP和NodeJs開發(fā)的應(yīng)用如何共用Session
這篇文章主要介紹了PHP和NodeJs開發(fā)的應(yīng)用如何共用Session的相關(guān)資料及思路,需要的朋友可以參考下2015-04-04