docs.sheetjs.com/docz/docs/03-demos/02-grid/18-mui.md

230 lines
5.6 KiB
Markdown
Raw Normal View History

2023-05-11 06:17:10 +00:00
---
title: Material UI
pagination_prev: demos/frontend/index
pagination_next: demos/net/index
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
This demo covers the traditional Material UI Table as well as the MUI Data Grid.
## Material UI Table
The `Table` component abstracts the `<table>` element in HTML. `table_to_book`
can process a `ref` attached to the `Table` element:
```tsx
import TableContainer from '@mui/material/TableContainer';
import Table from '@mui/material/Table';
// ...
// highlight-next-line
import { useRef } from "react";
// ...
export default function BasicTable() {
// highlight-next-line
const tbl = useRef<HTMLTableElement>(null);
return ( <>
<button onClick={() => {
// highlight-next-line
const wb = utils.table_to_book(tbl.current);
writeFileXLSX(wb, "SheetJSMaterialUI.xlsx");
}}>Export</button>
<TableContainer {...}>
// highlight-next-line
<Table {...} ref={tbl}>
{/* ... material ui table machinations ... */}
</Table>
</TableContainer>
<>);
}
```
#### MUI Table Demo
<details open><summary><b>Complete Example</b> (click to hide)</summary>
:::note
This demo was last run on 2023 May 11 against Material UI 5.13.0 paired with
Emotion 11.11.0
:::
1) Create a new TypeScript `create-react-app` app:
```bash
npx create-react-app sheetjs-mui --template typescript
cd sheetjs-mui
```
2) Install dependencies:
<CodeBlock language="bash">{`\
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.13.0 @emotion/react@11.11.0 @emotion/styled@11.11.0`}
</CodeBlock>
3) Download [`App.tsx`](pathname:///mui/table/App.tsx) and replace `src/App.tsx`.
```bash
curl -L -o src/App.tsx https://docs.sheetjs.com/mui/table/App.tsx
```
4) Start the development server:
```bash
npm start
```
The script should open the live demo in a web browser. Click the "Export" button
to save the file. Open the generated file in a spreadsheet editor.
</details>
## Material UI Data Grid
[A complete example is included below.](#muidg-demo)
**Rows and Columns State**
MUI Data Grid state consists of an Array of column metadata and an Array of row
objects. Typically both are defined in state:
```js
// highlight-next-line
import { DataGrid, GridColDef } from "@mui/x-data-grid";
export default function App() {
const [rows, setRows] = useState([]);
const [columns, setColumns] = useState([]);
return ( <DataGrid columns={columns} rows={rows} /> );
}
```
The most generic data representation is an array of arrays. To sate the grid,
columns must be objects whose `field` property is the index converted to string:
```ts
import { WorkSheet, utils } from 'xlsx';
import { GridColDef } from "@mui/x-data-grid";
type Row = any[];
type RowCol = { rows: Row[]; columns: GridColDef[]; };
function ws_to_muidg(ws: WorkSheet): RowCol {
/* create an array of arrays */
const rows = utils.sheet_to_json(ws, { header: 1 });
/* create column array */
const range = utils.decode_range(ws["!ref"]||"A1");
const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
field: String(i), // MUIDG will access row["0"], row["1"], etc
headerName: utils.encode_col(i), // the column labels will be A, B, etc
editable: true // enable cell editing
}));
return { rows, columns }; // these can be fed to setRows / setColumns
}
```
In the other direction, a worksheet can be generated with `aoa_to_sheet`:
2023-09-24 03:59:48 +00:00
:::caution pass
2023-05-11 06:17:10 +00:00
`x-data-grid` does not properly preserve row array objects, so the row arrays
must be re-created. The snippet defines a `arrayify` function.
:::
```ts
import { WorkSheet, utils } from 'xlsx';
type Row = any[];
// highlight-start
function arrayify(rows: any[]): Row[] {
return rows.map(row => {
var length = Object.keys(row).length;
for(; length > 0; --length) if(row[length-1] != null) break;
return Array.from({length, ...row});
});
}
// highlight-end
function muidg_to_ws(rows: Row[]): WorkSheet {
return utils.aoa_to_sheet(arrayify(rows));
}
```
**Editing Cells**
2023-07-06 07:21:41 +00:00
The `processRowUpdate` callback prop receives the new row data. An event handler
can mutate state:
2023-05-11 06:17:10 +00:00
```tsx
import { GridRowModel } from "@mui/x-data-grid";
export default function App() {
// ...
const processRowUpdate = useCallback((rowNew: GridRowModel, rowOld: GridRowModel) => {
/* scan each column and manually set state entries */
for(var j = 0; j < columns.length; ++j) if(rowNew[j] != null) {
rows[rowNew.id][j] = isNaN(+rowNew[j]) ? rowNew[j] : +rowNew[j];
}
/* force a state update */
setRows(rows);
/* commit the new row */
return rowNew;
}, [columns, rows]);
return ( <DataGrid columns={columns} rows={rows} processRowUpdate={processRowUpdate} /> );
}
```
<!-- spellchecker-disable -->
#### MUIDG Demo
<!-- spellchecker-enable -->
<details open><summary><b>Complete Example</b> (click to hide)</summary>
:::note
This demo was last run on 2023 May 11 against MUI data grid 6.3.1 paired with
Emotion 11.11.0
:::
1) Create a new TypeScript `create-react-app` app:
```bash
npx create-react-app sheetjs-muidg --template typescript
cd sheetjs-muidg
```
2) Install dependencies:
<CodeBlock language="bash">{`\
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid @emotion/react @emotion/styled`}
</CodeBlock>
3) Download [`App.tsx`](pathname:///mui/dg/App.tsx) and replace `src/App.tsx`.
```bash
curl -L -o src/App.tsx https://docs.sheetjs.com/mui/dg/App.tsx
```
4) Start the development server:
```bash
npm start
```
When the page loads, it will fetch and process <https://sheetjs.com/pres.numbers>
</details>