MUI DataGrid导出Excel样式设置与层级下拉框实现问题
问题1:MUI DataGrid导出Excel定制样式解决方案
默认GridToolbarExport没有直接配置导出样式的API,需通过自定义导出逻辑,借助xlsx库实现样式定制:
步骤1:安装依赖
确保已安装xlsx(用于处理Excel文件):
npm install xlsx
步骤2:自定义导出函数
替换默认导出行为,实现三个样式需求:
import * as XLSX from 'xlsx'; import { utils, writeFile } from 'xlsx'; import { useGridApiRef } from '@mui/x-data-grid'; const customExport = (apiRef: GridApiRef) => { // 获取当前表格的可见列与数据 const visibleColumns = apiRef.current.getVisibleColumns(); const rowIds = apiRef.current.getSortedRowIds(); const rows = rowIds.map(id => apiRef.current.getRow(id)); // 转换为工作表数据结构:第一行是表头,后续是内容 const worksheetData = [ visibleColumns.map(col => col.headerName), ...rows.map(row => visibleColumns.map(col => row[col.field])) ]; const worksheet = utils.aoa_to_sheet(worksheetData); const range = utils.decode_range(worksheet['!ref'] || 'A1:Z100'); // 1. 表头样式:加粗字体、背景色、自动换行 for (let col = range.s.c; col <= range.e.c; col++) { const cellAddr = utils.encode_cell({ r: 0, c: col }); worksheet[cellAddr] = { ...worksheet[cellAddr], s: { font: { bold: true }, fill: { fgColor: { rgb: 'F0F0F0' } }, // 浅灰色背景 alignment: { wrapText: true } } }; } // 2. 内容单元格样式:自动换行、白色背景 for (let row = 1; row <= range.e.r; row++) { for (let col = range.s.c; col <= range.e.c; col++) { const cellAddr = utils.encode_cell({ r: row, c: col }); worksheet[cellAddr] = { ...worksheet[cellAddr], s: { alignment: { wrapText: true }, fill: { fgColor: { rgb: 'FFFFFF' } } } }; } } // 生成工作簿并下载 const workbook = utils.book_new(); utils.book_append_sheet(workbook, worksheet, 'Treatments'); writeFile(workbook, 'treatments_export.xlsx'); }; // 修改Toolbar组件,注入自定义导出逻辑 const TreatmentsToolbarForEvent = ({event, usersFromOpen, setUsersFromOpen}: IProps) => { const apiRef = useGridApiRef(); return ( <GridToolbarContainer> {/* @ts-ignore */} <GridToolbarColumnsButton sx={{ "& .MuiButton-startIcon": { marginLeft: "5px" } }} /> {/* @ts-ignore */} <GridToolbarFilterButton sx={{ "& .MuiButton-startIcon": { marginLeft: "5px" } }} /> <GridToolbarExport sx={{ "& .MuiButton-startIcon": { marginLeft: "5px" } }} apiRef={apiRef} exportfunc={() => customExport(apiRef)} /> <AddFormDialog entity={"treatments"} eventId={event.id} /> <FormDialogUsers event={event} open={usersFromOpen} setOpen={setUsersFromOpen} /> </GridToolbarContainer> ); };
关键样式说明
- 自动换行:通过
alignment.wrapText: true开启单元格文本换行 - 背景色:使用
fill.fgColor.rgb设置,十六进制颜色需去掉#并转为大写 - 标题加粗:给表头单元格添加
font.bold: true属性
问题2:DataGrid可编辑列实现层级选择(树形下拉)
默认singleSelect不支持层级结构,需自定义编辑单元格组件,结合MUI TreeView实现:
步骤1:准备层级数据结构
确保departmentOptions是带嵌套层级的数组,示例结构:
const departmentOptions = [ { id: 'dept-1', name: '技术部', children: [ { id: 'dept-1-1', name: '前端开发组' }, { id: 'dept-1-2', name: '后端开发组' } ]}, { id: 'dept-2', name: '人力资源部', children: [ { id: 'dept-2-1', name: '招聘组' } ]} ];
步骤2:自定义层级选择编辑组件
import { TreeView, TreeItem } from '@mui/x-tree-view'; import { GridRenderEditCellParams } from '@mui/x-data-grid'; // 递归渲染树形选项,通过padding实现层级缩进 const renderTreeNodes = (nodes: any[], level = 0) => { return nodes.map(node => ( <TreeItem key={node.id} nodeId={node.id} label={<span style={{ paddingLeft: `${level * 18}px` }}>{node.name}</span>} > {node.children && renderTreeNodes(node.children, level + 1)} </TreeItem> )); }; // 自定义编辑单元格组件 const HierarchySelectEditCell = (params: GridRenderEditCellParams) => { return ( <TreeView selected={params.value} onNodeSelect={(event, nodeId) => { // 更新单元格值 params.api.current.setEditCellValue({ id: params.id, field: params.field, value: nodeId }); // 选择完成后退出编辑模式 params.api.current.stopCellEditMode({ id: params.id, field: params.field }); }} > {renderTreeNodes(departmentSelectDropDown())} </TreeView> ); }; // 修改列配置,替换默认单选下拉为自定义组件 const columns: GridColDef[] = [ { field: 'department', headerName: strings().department, flex: 1, editable: isInSpecificEvent, // 移除默认的singleSelect配置,使用自定义编辑组件 renderEditCell: (params) => <HierarchySelectEditCell {...params} />, renderCell: (params) => { // 递归查找选中项的名称,用于单元格显示 const findNodeName = (nodes: any[], targetId: string): string => { for (const node of nodes) { if (node.id === targetId) return node.name; if (node.children) { const childName = findNodeName(node.children, targetId); if (childName) return childName; } } return ''; }; return findNodeName(departmentSelectDropDown(), params.row.department); } }, // 其他列配置... ];
核心逻辑说明
- 用
TreeView实现层级选择,通过paddingLeft模拟层级缩进效果 - 自定义
renderEditCell替换默认的单选下拉组件 - 实现递归函数匹配选中项名称,确保单元格正常显示层级文本
- 选择完成后调用
setEditCellValue更新数据并关闭编辑模式
内容的提问来源于stack exchange,提问作者Thekatsman
相关产品推荐
相关产品推荐

