230 lines
5.5 KiB
Markdown
230 lines
5.5 KiB
Markdown
|
---
|
||
|
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`:
|
||
|
|
||
|
:::caution
|
||
|
|
||
|
`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**
|
||
|
|
||
|
The `processRowUpdate` prop receives the new row data, allowing for easy
|
||
|
state mutation:
|
||
|
|
||
|
```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>
|