You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js开源方案:Excel单元格取消合并的最优实现方式

解决方案:JS端高效处理Excel取消合并单元格

优先推荐:SheetJS (xlsx 库)

SheetJS是JS生态中处理Excel最成熟的库之一,性能优异,能轻松应对4万行×22列的大数据量,且对合并单元格的处理逻辑清晰。

核心实现思路

  1. 读取Excel文件时,同时获取工作表的合并单元格区域列表
  2. 遍历每个合并区域,将区域左上角单元格的值,填充到该区域内的所有空白单元格中
  3. 完成后即可得到取消合并后的完整数据

代码示例

import * as XLSX from 'xlsx';
import { readBinaryFile } from '@tauri-apps/api/fs';

// 读取本地Excel文件(Tauri环境)
async function processExcel(filePath) {
  const fileData = await readBinaryFile(filePath);
  const workbook = XLSX.read(new Uint8Array(fileData), { type: 'array' });
  const sheetName = workbook.SheetNames[0];
  const worksheet = workbook.Sheets[sheetName];

  // 获取所有合并单元格区域
  const merges = worksheet['!merges'] || [];

  // 遍历每个合并区域
  merges.forEach(merge => {
    // 获取合并区域的起始和结束单元格坐标
    const start = XLSX.utils.decode_cell(merge.s);
    const end = XLSX.utils.decode_cell(merge.e);
    // 获取左上角单元格的值
    const value = worksheet[XLSX.utils.encode_cell(start)]?.v;

    // 遍历合并区域内的所有单元格,填充值
    for (let row = start.r; row <= end.r; row++) {
      for (let col = start.c; col <= end.c; col++) {
        const cellAddr = XLSX.utils.encode_cell({ r: row, c: col });
        // 只填充空白单元格(避免覆盖已有值)
        if (!worksheet[cellAddr]) {
          worksheet[cellAddr] = { v: value };
        }
      }
    }
  });

  // 将处理后的工作表转为JSON数据(或导出为新Excel)
  const jsonData = XLSX.utils.sheet_to_json(worksheet);
  return jsonData;
}

备选方案:ExcelJS

如果需要更精细化的Excel操作(比如流式读写超大文件),可以用ExcelJS。它支持直接操作合并单元格,且内存占用更低,适合极端大数据场景。

代码示例

import ExcelJS from 'exceljs';
import { readFile } from '@tauri-apps/api/fs';

async function processExcelWithExcelJS(filePath) {
  const workbook = new ExcelJS.Workbook();
  // 读取本地文件(Tauri环境下需转成Buffer)
  const fileBuffer = await readFile(filePath, { readMode: 'binary' });
  await workbook.xlsx.load(fileBuffer);

  const worksheet = workbook.getWorksheet(1);

  // 获取所有合并单元格区域
  const mergeCells = worksheet.mergedCells || [];

  mergeCells.forEach(mergeRange => {
    // 解析合并区域的坐标(比如"A1:C3")
    const [startAddr, endAddr] = mergeRange.split(':');
    const startCell = worksheet.getCell(startAddr);
    const value = startCell.value;

    // 获取区域的行和列范围
    const startRow = startCell.row.number;
    const endRow = worksheet.getCell(endAddr).row.number;
    const startCol = startCell.col.number;
    const endCol = worksheet.getCell(endAddr).col.number;

    // 填充所有合并单元格
    for (let row = startRow; row <= endRow; row++) {
      for (let col = startCol; col <= endCol; col++) {
        const cell = worksheet.getCell(row, col);
        if (!cell.value) {
          cell.value = value;
        }
      }
    }
    // 取消合并(可选,若需要物理取消合并单元格)
    worksheet.unMergeCells(mergeRange);
  });

  // 导出处理后的文件或转为JSON
  const jsonData = [];
  worksheet.eachRow({ includeEmpty: false }, row => {
    jsonData.push(row.values);
  });
  return jsonData;
}

为什么放弃xlsx-populate和openpyxl?

  • xlsx-populate的合并单元格取值逻辑存在局限性,对多行多列的合并区域没有自动映射值到子单元格的机制,手动处理的API支持不足
  • openpyxl作为Python库,跨语言调用(Tauri调用Python)本身会有性能损耗,且Python单线程处理大数据的效率远低于JS,4万行数据的延迟会非常明显

内容的提问来源于stack exchange,提问作者Mr Day2Day

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:15:41