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