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
相关产品推荐
相关产品推荐

