forked from sheetjs/docs.sheetjs.com
		
	mui
This commit is contained in:
		
							parent
							
								
									e6fc787cd2
								
							
						
					
					
						commit
						e1584a41a3
					
				@ -161,7 +161,11 @@ However, this does not handle merge cells well!
 | 
			
		||||
 | 
			
		||||
The `sheet_to_html` function generates HTML that is aware of merges and other
 | 
			
		||||
worksheet features.  React `dangerouslySetInnerHTML` attribute allows code to
 | 
			
		||||
set the `innerHTML` attribute, effectively inserting the code into the page:
 | 
			
		||||
set the `innerHTML` attribute, effectively inserting the code into the page.
 | 
			
		||||
 | 
			
		||||
In this example, the component attaches a `ref` to the `DIV` container. During
 | 
			
		||||
export, the first `TABLE` child element can be parsed with `table_to_book` to
 | 
			
		||||
generate a workbook object.
 | 
			
		||||
 | 
			
		||||
```jsx title="src/SheetJSReactHTML.js"
 | 
			
		||||
import React, { useCallback, useEffect, useRef, useState } from "react";
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										229
									
								
								docz/docs/03-demos/02-grid/18-mui.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										229
									
								
								docz/docs/03-demos/02-grid/18-mui.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,229 @@
 | 
			
		||||
---
 | 
			
		||||
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>
 | 
			
		||||
@ -102,117 +102,7 @@ with other buttons and components on the page.
 | 
			
		||||
 | 
			
		||||
### Material UI Data Grid
 | 
			
		||||
 | 
			
		||||
Material UI Data Grid and React Data Grid share many state patterns and idioms.
 | 
			
		||||
Differences from ["React Data Grid"](/docs/demos/grid/rdg) will be highlighted.
 | 
			
		||||
 | 
			
		||||
[A complete example is included below.](#muidg-demo)
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
 | 
			
		||||
Despite presenting an editable UI, Material UI Data Grid version `5.17.0` does
 | 
			
		||||
not update the state when values are changed. The demo uses the React Data Grid
 | 
			
		||||
editable structure in the hopes that a future version does support state.
 | 
			
		||||
 | 
			
		||||
Until the issues are resolved, "React Data Grid" is an excellent choice.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
**Rows and Columns State**
 | 
			
		||||
 | 
			
		||||
The analogue of `Column` is `GridColDef`.  The simple structure looks like:
 | 
			
		||||
 | 
			
		||||
```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} onRowsChange={setRows} /> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
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';
 | 
			
		||||
// highlight-next-line
 | 
			
		||||
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) => ({
 | 
			
		||||
    // highlight-start
 | 
			
		||||
    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
 | 
			
		||||
    // highlight-end
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  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));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<!-- spellchecker-disable -->
 | 
			
		||||
 | 
			
		||||
#### MUIDG Demo
 | 
			
		||||
 | 
			
		||||
<!-- spellchecker-enable -->
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Complete Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
0) [Follow the React Data Grid demo](#rdg-demo) and generate the sample app.
 | 
			
		||||
 | 
			
		||||
1) 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>
 | 
			
		||||
 | 
			
		||||
2) Download [`App.tsx`](pathname:///muidg/App.tsx) and replace `src/App.tsx`.
 | 
			
		||||
 | 
			
		||||
3) run `npm start`.  When you load the page in the browser, it will attempt to
 | 
			
		||||
   fetch <https://sheetjs.com/pres.numbers> and load the data.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
**[The exposition has been moved to a separate page.](/docs/demos/grid/mui#material-ui-data-grid)**
 | 
			
		||||
 | 
			
		||||
<!-- spellchecker-disable -->
 | 
			
		||||
 | 
			
		||||
@ -282,154 +172,8 @@ document.body.removeChild(tbl);
 | 
			
		||||
 | 
			
		||||
### React
 | 
			
		||||
 | 
			
		||||
The typical solution is to attach a Ref to the table element.  The `current`
 | 
			
		||||
property will be a live reference which plays nice with `table_to_book`:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
// highlight-next-line
 | 
			
		||||
import { useRef } from "react";
 | 
			
		||||
 | 
			
		||||
export default function ReactTable() {
 | 
			
		||||
// highlight-next-line
 | 
			
		||||
  const tbl = useRef(null);
 | 
			
		||||
 | 
			
		||||
  return ( <>
 | 
			
		||||
    <button onClick={() => {
 | 
			
		||||
      // highlight-next-line
 | 
			
		||||
      const wb = XLSX.utils.table_to_book(tbl.current);
 | 
			
		||||
      XLSX.writeFile(wb, "ReactTable.xlsx");
 | 
			
		||||
    }}>Export</button>
 | 
			
		||||
    // highlight-next-line
 | 
			
		||||
    <table ref={tbl}>
 | 
			
		||||
    {/* ... TR and TD/TH elements ... */}
 | 
			
		||||
    </table>
 | 
			
		||||
  </> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
**[The exposition has been moved to a separate page.](/docs/demos/frontend/react#html)**
 | 
			
		||||
 | 
			
		||||
### Material UI Table
 | 
			
		||||
 | 
			
		||||
The `Table` component abstracts the `<table>` element in HTML.
 | 
			
		||||
 | 
			
		||||
```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={() => {
 | 
			
		||||
      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>
 | 
			
		||||
  <>);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Complete Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
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`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
3) Replace `src/App.tsx` with the following code. This is based on the official
 | 
			
		||||
Material UI Table example.  Differences are highlighted.
 | 
			
		||||
 | 
			
		||||
```tsx title="src/App.tsx"
 | 
			
		||||
// highlight-start
 | 
			
		||||
import React, { useEffect, useState, useRef, ChangeEvent } from "react";
 | 
			
		||||
import { utils, writeFileXLSX } from 'xlsx';
 | 
			
		||||
// highlight-end
 | 
			
		||||
import Table from '@mui/material/Table';
 | 
			
		||||
import TableBody from '@mui/material/TableBody';
 | 
			
		||||
import TableCell from '@mui/material/TableCell';
 | 
			
		||||
import TableContainer from '@mui/material/TableContainer';
 | 
			
		||||
import TableHead from '@mui/material/TableHead';
 | 
			
		||||
import TableRow from '@mui/material/TableRow';
 | 
			
		||||
import Paper from '@mui/material/Paper';
 | 
			
		||||
 | 
			
		||||
function createData(
 | 
			
		||||
  name: string,
 | 
			
		||||
  calories: number,
 | 
			
		||||
  fat: number,
 | 
			
		||||
  carbs: number,
 | 
			
		||||
  protein: number,
 | 
			
		||||
) {
 | 
			
		||||
  return { name, calories, fat, carbs, protein };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rows = [
 | 
			
		||||
  createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
 | 
			
		||||
  createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
 | 
			
		||||
  createData('Eclair', 262, 16.0, 24, 6.0),
 | 
			
		||||
  createData('Cupcake', 305, 3.7, 67, 4.3),
 | 
			
		||||
  createData('Gingerbread', 356, 16.0, 49, 3.9),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default function BasicTable() {
 | 
			
		||||
  // highlight-start
 | 
			
		||||
  const tbl = useRef<HTMLTableElement>(null);
 | 
			
		||||
  return ( <>
 | 
			
		||||
    <button onClick={() => {
 | 
			
		||||
      const wb = utils.table_to_book(tbl.current);
 | 
			
		||||
      writeFileXLSX(wb, "SheetJSMaterialUI.xlsx");
 | 
			
		||||
    }}>Export</button>
 | 
			
		||||
    // highlight-end
 | 
			
		||||
    <TableContainer component={Paper}>
 | 
			
		||||
      // highlight-next-line
 | 
			
		||||
      <Table sx={{ minWidth: 650 }} aria-label="simple table" ref={tbl}>
 | 
			
		||||
        <TableHead>
 | 
			
		||||
          <TableRow>
 | 
			
		||||
            <TableCell>Dessert (100g serving)</TableCell>
 | 
			
		||||
            <TableCell align="right">Calories</TableCell>
 | 
			
		||||
            <TableCell align="right">Fat (g)</TableCell>
 | 
			
		||||
            <TableCell align="right">Carbs (g)</TableCell>
 | 
			
		||||
            <TableCell align="right">Protein (g)</TableCell>
 | 
			
		||||
          </TableRow>
 | 
			
		||||
        </TableHead>
 | 
			
		||||
        <TableBody>
 | 
			
		||||
          {rows.map((row) => (
 | 
			
		||||
            <TableRow
 | 
			
		||||
              key={row.name}
 | 
			
		||||
              sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
 | 
			
		||||
            >
 | 
			
		||||
              <TableCell component="th" scope="row">
 | 
			
		||||
                {row.name}
 | 
			
		||||
              </TableCell>
 | 
			
		||||
              <TableCell align="right">{row.calories}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.fat}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.carbs}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.protein}</TableCell>
 | 
			
		||||
            </TableRow>
 | 
			
		||||
          ))}
 | 
			
		||||
        </TableBody>
 | 
			
		||||
      </Table>
 | 
			
		||||
    </TableContainer>
 | 
			
		||||
    // highlight-next-line
 | 
			
		||||
  </> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) run `npm start`.  Click the "Export" button and inspect the generated file.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
**[The exposition has been moved to a separate page.](/docs/demos/grid/mui#material-ui-table)**
 | 
			
		||||
 | 
			
		||||
@ -170,8 +170,8 @@ const aoa = [ ["Hash"], [key] ].concat(Object.entries(values));
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 February 23 with Redis 7.0.8, Redis connector
 | 
			
		||||
module 4.6.4 and NodeJS 18.14.2.
 | 
			
		||||
This demo was last tested on 2023 May 11 with Redis 7.0.11, Redis connector
 | 
			
		||||
module 4.6.6 and NodeJS 20.1.0.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -179,19 +179,28 @@ module 4.6.4 and NodeJS 18.14.2.
 | 
			
		||||
 | 
			
		||||
The most recent version of the `redis` node module does not work with most
 | 
			
		||||
versions of NodeJS. It is "ESM-only", requiring NodeJS 18 or later. As a result,
 | 
			
		||||
this demo also requires NodeJS version 18.
 | 
			
		||||
 | 
			
		||||
Questions regarding the `redis` library and the decision to drop traditional
 | 
			
		||||
NodeJS "CommonJS" module support should be directed to the Redis team.
 | 
			
		||||
this demo also requires NodeJS version 18 or later.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
0) Set up and start a local Redis server.  On Intel macOS:
 | 
			
		||||
0) Set up and start a local Redis server.
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on Intel macOS.  Redis was installed with:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
brew install redis@7.0.8
 | 
			
		||||
brew install redis@7.0.11
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The following command started the server process:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
/usr/local/opt/redis/bin/redis-server /usr/local/etc/redis.conf
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Download the following scripts:
 | 
			
		||||
 | 
			
		||||
- [`SheetJSRedis.mjs`](pathname:///nosql/SheetJSRedis.mjs)
 | 
			
		||||
@ -202,13 +211,18 @@ curl -LO https://docs.sheetjs.com/nosql/SheetJSRedis.mjs
 | 
			
		||||
curl -LO https://docs.sheetjs.com/nosql/SheetJSRedisTest.mjs
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install dependencies and run:
 | 
			
		||||
2) Install dependencies:
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="bash">{`\
 | 
			
		||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.4
 | 
			
		||||
node SheetJSRedisTest.mjs`}
 | 
			
		||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.6`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
3) Run the test script:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
node SheetJSRedisTest.mjs
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Inspect the output and compare with the data in `SheetJSRedisTest.mjs`.
 | 
			
		||||
 | 
			
		||||
Open `SheetJSRedis.xlsx` and verify the columns have the correct data
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,22 @@ sidebar_position: 2
 | 
			
		||||
# Hyperlinks
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
  <summary><b>Format Support</b> (click to show)</summary>
 | 
			
		||||
  <summary><b>File Format Support</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
**Cell Hyperlinks**: XLSX/M, XLSB, BIFF8 XLS, XLML, ODS, HTML
 | 
			
		||||
| Formats           | Link  | Tooltip | Storage Representation |
 | 
			
		||||
|:------------------|:-----:|:-------:|:-----------------------|
 | 
			
		||||
| XLSX / XLSM       |   ✔   |    ✔    | Cell Link + Tooltip    |
 | 
			
		||||
| XLSB              |   ✔   |    ✔    | Cell Link + Tooltip    |
 | 
			
		||||
| XLS (BIFF8)       |   ✔   |    ✔    | Cell Link + Tooltip    |
 | 
			
		||||
| XLML              |   ✔   |    ✔    | Cell Link + Tooltip    |
 | 
			
		||||
| ODS / FODS / UOS  |   ✔   |         | Span Link + Tooltip    |
 | 
			
		||||
| HTML              |   ✔   |    *    | Span Link              |
 | 
			
		||||
| NUMBERS           |       |    *    | Span Link **           |
 | 
			
		||||
 | 
			
		||||
**Tooltips**: XLSX/M, XLSB, BIFF8 XLS, XLML
 | 
			
		||||
Asterisks (*) mark features that are not supported by the file formats.
 | 
			
		||||
 | 
			
		||||
For "Span Link" formats, parsers apply the first hyperlink to the entire cell
 | 
			
		||||
and writers apply the hyperlink to the entire cell text.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
@ -26,9 +37,19 @@ ws["A1"].l = { Target: "https://sheetjs.com", Tooltip: "Find us @ SheetJS.com!"
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
Following traditional software, hyperlinks are applied to entire cell objects.
 | 
			
		||||
Some formats (including HTML) attach links to text spans. The parsers apply the
 | 
			
		||||
first link to the entire cell. Writers apply links to the entire cell text.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
Excel does not automatically style hyperlinks.  They will be displayed using
 | 
			
		||||
the default cell style. <a href="https://sheetjs.com/pro">SheetJS Pro Basic</a>
 | 
			
		||||
extends this export with support for hyperlink styling.
 | 
			
		||||
the default cell style.
 | 
			
		||||
 | 
			
		||||
<a href="https://sheetjs.com/pro">SheetJS Pro Basic</a> includes support for
 | 
			
		||||
general hyperlink styling.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import React, { useEffect, useState, ChangeEvent } from "react";
 | 
			
		||||
import { DataGrid, GridColDef } from "@mui/x-data-grid";
 | 
			
		||||
import React, { useCallback, useEffect, useState, ChangeEvent } from "react";
 | 
			
		||||
import { DataGrid, GridColDef, GridRowModel } from "@mui/x-data-grid";
 | 
			
		||||
import { read, utils, WorkSheet, writeFile } from "xlsx";
 | 
			
		||||
 | 
			
		||||
import './App.css';
 | 
			
		||||
@ -87,6 +87,12 @@ export default function App() {
 | 
			
		||||
    writeFile(wb, "SheetJSMUIDG." + ext);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const processRowUpdate = useCallback((rowNew: GridRowModel, rowOld: GridRowModel) => {
 | 
			
		||||
    for(var j = 0; j < columns.length; ++j) if(rowNew[j] != null) rows[rowNew.id][j] = isNaN(+rowNew[j]) ? rowNew[j] : +rowNew[j];
 | 
			
		||||
    setRows(rows);
 | 
			
		||||
    return rowNew;
 | 
			
		||||
  }, [columns, rows]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <h3>SheetJS × MUI Data Grid Demo</h3>
 | 
			
		||||
@ -99,7 +105,7 @@ export default function App() {
 | 
			
		||||
        </p>
 | 
			
		||||
        <div className="flex-cont"><b>Current Sheet: {current}</b></div>
 | 
			
		||||
        <div style={{width:"100%", height:400}}>
 | 
			
		||||
          <DataGrid columns={columns} rows={rows} experimentalFeatures={{ newEditingApi: true }} />
 | 
			
		||||
          <DataGrid columns={columns} rows={rows} processRowUpdate={processRowUpdate} />
 | 
			
		||||
        </div>
 | 
			
		||||
        <p>Click one of the buttons to create a new file with the modified data</p>
 | 
			
		||||
        <div className="flex-cont">{["xlsx", "xlsb", "xls"].map((ext) => (
 | 
			
		||||
							
								
								
									
										66
									
								
								docz/static/mui/table/App.tsx
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										66
									
								
								docz/static/mui/table/App.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
import React, { useRef } from "react";
 | 
			
		||||
import { utils, writeFileXLSX } from 'xlsx';
 | 
			
		||||
import Table from '@mui/material/Table';
 | 
			
		||||
import TableBody from '@mui/material/TableBody';
 | 
			
		||||
import TableCell from '@mui/material/TableCell';
 | 
			
		||||
import TableContainer from '@mui/material/TableContainer';
 | 
			
		||||
import TableHead from '@mui/material/TableHead';
 | 
			
		||||
import TableRow from '@mui/material/TableRow';
 | 
			
		||||
import Paper from '@mui/material/Paper';
 | 
			
		||||
 | 
			
		||||
function createData(
 | 
			
		||||
  name: string,
 | 
			
		||||
  calories: number,
 | 
			
		||||
  fat: number,
 | 
			
		||||
  carbs: number,
 | 
			
		||||
  protein: number,
 | 
			
		||||
) {
 | 
			
		||||
  return { name, calories, fat, carbs, protein };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rows = [
 | 
			
		||||
  createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
 | 
			
		||||
  createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
 | 
			
		||||
  createData('Eclair', 262, 16.0, 24, 6.0),
 | 
			
		||||
  createData('Cupcake', 305, 3.7, 67, 4.3),
 | 
			
		||||
  createData('Gingerbread', 356, 16.0, 49, 3.9),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default function BasicTable() {
 | 
			
		||||
  const tbl = useRef<HTMLTableElement>(null);
 | 
			
		||||
  return ( <>
 | 
			
		||||
    <button onClick={() => {
 | 
			
		||||
      const wb = utils.table_to_book(tbl.current);
 | 
			
		||||
      writeFileXLSX(wb, "SheetJSMaterialUI.xlsx");
 | 
			
		||||
    }}>Export</button>
 | 
			
		||||
    <TableContainer component={Paper}>
 | 
			
		||||
      <Table sx={{ minWidth: 650 }} aria-label="simple table" ref={tbl}>
 | 
			
		||||
        <TableHead>
 | 
			
		||||
          <TableRow>
 | 
			
		||||
            <TableCell>Dessert (100g serving)</TableCell>
 | 
			
		||||
            <TableCell align="right">Calories</TableCell>
 | 
			
		||||
            <TableCell align="right">Fat (g)</TableCell>
 | 
			
		||||
            <TableCell align="right">Carbs (g)</TableCell>
 | 
			
		||||
            <TableCell align="right">Protein (g)</TableCell>
 | 
			
		||||
          </TableRow>
 | 
			
		||||
        </TableHead>
 | 
			
		||||
        <TableBody>
 | 
			
		||||
          {rows.map((row) => (
 | 
			
		||||
            <TableRow
 | 
			
		||||
              key={row.name}
 | 
			
		||||
              sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
 | 
			
		||||
            >
 | 
			
		||||
              <TableCell component="th" scope="row">
 | 
			
		||||
                {row.name}
 | 
			
		||||
              </TableCell>
 | 
			
		||||
              <TableCell align="right">{row.calories}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.fat}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.carbs}</TableCell>
 | 
			
		||||
              <TableCell align="right">{row.protein}</TableCell>
 | 
			
		||||
            </TableRow>
 | 
			
		||||
          ))}
 | 
			
		||||
        </TableBody>
 | 
			
		||||
      </Table>
 | 
			
		||||
    </TableContainer>
 | 
			
		||||
  </> );
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user