如何通过独立按钮导出Material-UI DataGrid数据至Excel(不使用Toolbar)
实现Material-UI DataGrid独立导出按钮(不使用自带Toolbar)
核心方案
通过DataGrid的apiRef获取表格当前的有效数据(包括经过筛选、排序后的行),将数据转换为可下载的CSV格式,再配合自定义的Material-UI Button作为独立导出控件,完全不需要依赖DataGrid自带的Toolbar组件。
实现步骤
- 引入所需依赖:除了
DataGrid,还需要引入Material-UI的Button,以及useGridApiRef来获取表格实例的引用。 - 创建apiRef实例:将其传递给DataGrid组件,用于后续获取表格数据。
- 编写导出逻辑:
- 通过
apiRef.current.getRenderedRows()获取当前页面渲染的所有行(需要全量数据可用getRows()) - 提取列的
headerName作为CSV表头,提取行数据对应字段的值 - 将表头和行数据拼接成CSV格式的字符串
- 创建临时下载链接,触发浏览器下载操作
- 通过
- 渲染独立按钮:在DataGrid外部放置自定义按钮,绑定导出函数。
完整代码示例
import { DataGrid, useGridApiRef } from "@material-ui/data-grid"; import Button from "@material-ui/core/Button"; const columns = [ { field: "id", headerName: "ID", flex: 1 }, { field: "firstName", headerName: "First name", flex: 1 }, { field: "lastName", headerName: "Last name", flex: 1 }, { field: "age", headerName: "Age", type: "number", flex: 1 }, { field: "fullName", headerName: "Full name", description: "This column has a value getter and is not sortable.", sortable: false, flex: 1, valueGetter: (params) => `${params.getValue(params.id, "firstName") || ""} ${params.getValue(params.id, "lastName") || ""}` } ]; const rows = [ { id: 1, lastName: "Snow", firstName: "Jon", age: 35 }, { id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 }, { id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 }, { id: 4, lastName: "Stark", firstName: "Arya", age: 16 }, { id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null }, { id: 6, lastName: "Melisandre", firstName: null, age: 150 }, { id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 }, { id: 8, lastName: "Frances", firstName: "Rossini", age: 36 }, { id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 } ]; export default function App() { const apiRef = useGridApiRef(); // 导出数据为CSV的函数 const exportToCSV = () => { // 获取当前渲染的所有行(需要全量数据改用apiRef.current.getRows()) const rows = apiRef.current.getRenderedRows(); if (!rows.length) return; // 提取CSV表头:使用列的headerName const headers = columns.map(col => col.headerName); // 提取行数据:处理valueGetter生成的列(比如fullName) const rowsData = rows.map(row => { return columns.map(col => { // 如果列有valueGetter,调用它获取值 if (col.valueGetter) { return col.valueGetter({ getValue: (id, field) => row[field], id: row.id, row }); } // 普通列直接取对应字段值,空值处理为空字符串 return row[col.field] ?? ""; }); }); // 拼接CSV内容,处理逗号和引号转义 const csvContent = [ headers.join(","), ...rowsData.map(row => row.map(cell => `"${cell.toString().replace(/"/g, '""')}"`).join(",")) ].join("\n"); // 创建下载链接并触发下载 const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.setAttribute("download", "data-grid-export.csv"); document.body.appendChild(link); link.click(); document.body.removeChild(link); }; return ( <> <div style={{ width: "100%", marginBottom: "16px" }}> {/* 独立导出按钮 */} <Button variant="contained" color="primary" onClick={exportToCSV}> 导出数据 </Button> </div> <div style={{ height: 400, width: "100%" }}> <DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection apiRef={apiRef} /> </div> </> ); }
注意事项
- 若需导出全部数据(而非当前页面),将
getRenderedRows()替换为apiRef.current.getRows()即可。 - 代码处理了
valueGetter生成的列,确保导出数据与表格显示一致。 - 对CSV内容做了转义处理,避免包含逗号或引号的内容破坏CSV格式。
内容的提问来源于stack exchange,提问作者Rajat
相关产品推荐
相关产品推荐

