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

React JS导出数组为xlsx格式Excel时末尾列数据为空问题

问题成因
  • 直接原因是SheetJS的 XLSX.utils.json_to_sheet 方法仅支持字符串、数字、布尔这类基础类型值的自动序列化,你导出为空的最后三列,单元格取到的值是数组、日期对象这类引用类型,方法无法识别就会直接渲染为空单元格,和你推测的日期字段为数组类型的判断一致。
  • 代码存在两个附带问题:一是你定义的MIME类型application/vnd.ms-excel;charset=utf-8是旧版xls格式的标识,和实际导出的xlsx格式不匹配,部分Excel版本打开时会弹出格式损坏提示;二是你用data.map执行删除字段的操作属于无效写法,map本身返回新数组不会修改原数组,只是delete操作直接修改了原对象才达到了删字段的效果,逻辑不规范。
修复方案
  • 组装导出数据时,提前对所有非基础类型的单元格值做序列化处理,转换成SheetJS可识别的基础类型
  • 替换为xlsx格式对应的正确MIME类型
  • 提前过滤不需要导出的字段,去掉无意义的map遍历删除逻辑

修复后的核心代码如下:

import {
    GridToolbarContainer,
    gridFilteredSortedRowIdsSelector,
    gridVisibleColumnFieldsSelector
} from "@mui/x-data-grid";
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';

const CustomToolbar = () => {
    const apiRef = useGridApiContext();
    // 修正为xlsx格式对应的正确MIME类型
    const fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
    const fileExtension = ".xlsx";
    const fileName = "myfile";
    const buttonBaseProps = {
        color: "primary",
        size: "small",
    };

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

    const handleExportFilteredRows = () => {
        const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
        const visibleColumnsField = gridVisibleColumnFieldsSelector(apiRef);
        // 提前过滤不需要导出的字段,无需后续遍历删除
        const exportFields = visibleColumnsField.filter(field => !['_check_', 'action'].includes(field));

        const exportData = filteredSortedRowIds.map((id) => {
            const row = {};
            exportFields.forEach((field) => {
                const cellValue = apiRef.current.getCellParams(id, field).value;
                // 处理数组类型值:拼接为逗号分隔的字符串
                if (Array.isArray(cellValue)) {
                    row[field] = cellValue.map(item => {
                        // 数组内如果是日期对象,转为YYYY-MM-DD格式字符串
                        if (item instanceof Date) {
                            return item.toISOString().slice(0, 10);
                        }
                        return String(item);
                    }).join(', ');
                }
                // 处理单个日期对象
                else if (cellValue instanceof Date) {
                    row[field] = cellValue.toISOString().slice(0, 10);
                }
                // 空值统一转为空字符串,避免出现undefined/null的原始文本
                else {
                    row[field] = cellValue ?? '';
                }
            });
            return row;
        });

        Export(exportData, fileName);
    };

    return (
        <GridToolbarContainer>
            <Button
                {...buttonBaseProps}
                onClick={handleExportFilteredRows}
            >
                Filtered rows
            </Button>
        </GridToolbarContainer>
    );
}

如果你表格里的日期是Dayjs、Moment包装对象或者时间戳格式,只需要在类型判断分支里增加对应的格式转换逻辑即可,只要保证最终传入json_to_sheet的每个字段值都是基础类型,就不会出现空列问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:15:45