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

导出XLSX表格前如何自定义行数据?

问题描述

现有如下数据数组:

const data = [
    { id: 1, serviceId: 1, title: "A", model: "A", },
    { id: 1, serviceId: 1, title: "T", model: "b", },
    { id: 1, serviceId: 2, title: "R", model: "A", },
    { id: 2, serviceId: 55, title: "Q", model: "A", },
    { id: 3, serviceId: 58, title: "S", model: "p", },
    { id: 3, serviceId: 58, title: "S", model: "m", },
    { id: 3, serviceId: 66, title: "y", model: "A", }
];

使用以下ExportToExcel组件将数据导出为XLSX文件:

export const ExportToExcel = ({ apiData, fileName }) => {
    const fileType =
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8";
    const fileExtension = ".xlsx";

    const exportToCSV = (apiData, fileName) => {
        const ws = XLSX.utils.json_to_sheet(apiData);
        const wb = { Sheets: { data: ws }, SheetNames: ["data"] };
        const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
        const data = new Blob([excelBuffer], { type: fileType });
        FileSaver.saveAs(data, fileName + fileExtension);
    };

    return (
        <Button
            onClick={(e) => exportToCSV(apiData, fileName)}
            sx={{ m: 2 }}
            variant="contained"
        >
            Export as xlsx
        </Button>
    );
};

组件调用方式:

<ExportToExcel apiData={data} fileName={fileName}/>

希望导出时实现合并相同id、serviceId的行的效果,之前尝试循环分组实现但代码冗余,求更简洁的实现方法。

解决方案

可以利用xlsx库的单元格合并能力,结合分组逻辑快速实现,以下是优化后的代码:

方案1:用Lodash简化分组

先安装Lodash(若未安装):

npm install lodash

修改组件代码:

import _ from 'lodash';
import XLSX from 'xlsx';
import FileSaver from 'file-saver';
import { Button } from '@mui/material';

export const ExportToExcel = ({ apiData, fileName }) => {
    const fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8";
    const fileExtension = ".xlsx";

    const exportToXLSX = (apiData, fileName) => {
        // 按id+serviceId组合键分组
        const groupedData = _.groupBy(apiData, item => `${item.id}-${item.serviceId}`);
        
        // 预处理数据:每组仅第一条保留id和serviceId,其余置空
        const processedData = [];
        Object.values(groupedData).forEach(group => {
            group.forEach((item, idx) => {
                processedData.push({
                    id: idx === 0 ? item.id : '',
                    serviceId: idx === 0 ? item.serviceId : '',
                    title: item.title,
                    model: item.model
                });
            });
        });

        // 生成工作表
        const ws = XLSX.utils.json_to_sheet(processedData);
        // 初始化合并规则数组
        ws['!merges'] = [];

        // 计算并设置合并范围
        let startRow = 1; // 表头占第0行,数据从第1行开始(xlsx行索引从0起)
        Object.values(groupedData).forEach(group => {
            const rowLen = group.length;
            if (rowLen > 1) {
                // 合并id列(A列,索引0)
                ws['!merges'].push({
                    s: { r: startRow, c: 0 },
                    e: { r: startRow + rowLen - 1, c: 0 }
                });
                // 合并serviceId列(B列,索引1)
                ws['!merges'].push({
                    s: { r: startRow, c: 1 },
                    e: { r: startRow + rowLen - 1, c: 1 }
                });
            }
            startRow += rowLen;
        });

        // 生成工作簿并导出
        const wb = { Sheets: { data: ws }, SheetNames: ["data"] };
        const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
        const dataBlob = new Blob([excelBuffer], { type: fileType });
        FileSaver.saveAs(dataBlob, fileName + fileExtension);
    };

    return (
        <Button
            onClick={(e) => exportToXLSX(apiData, fileName)}
            sx={{ m: 2 }}
            variant="contained"
        >
            Export as xlsx
        </Button>
    );
};

方案2:原生JS分组(无需Lodash)

如果不想引入第三方库,用原生JS的reduce实现分组:

// 替换方案1中的groupBy逻辑
const groupedData = apiData.reduce((acc, item) => {
    const key = `${item.id}-${item.serviceId}`;
    acc[key] = acc[key] || [];
    acc[key].push(item);
    return acc;
}, {});

核心逻辑说明

  1. 分组:通过id和serviceId的组合键把数据分成多组;
  2. 数据预处理:每组仅第一条保留id和serviceId值,其余置空,避免合并后重复显示内容;
  3. 设置合并规则:通过ws['!merges']数组定义单元格合并范围,每个规则包含起始(s)和结束(e)的行、列索引;
  4. 导出:生成工作簿并通过FileSaver保存为XLSX文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:22:46