diff --git a/docz/docs/03-demos/04-grid/18-mui.md b/docz/docs/03-demos/04-grid/18-mui.md index 7f55194..3970dd8 100644 --- a/docz/docs/03-demos/04-grid/18-mui.md +++ b/docz/docs/03-demos/04-grid/18-mui.md @@ -5,44 +5,174 @@ pagination_next: demos/net/index --- import current from '/version.js'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; -This demo covers the traditional Material UI Table as well as the MUI Data Grid. +Material UI is a collection of ReactJS Components that follows the +[Google Material Design system](https://material.io/) + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo uses Material UI and SheetJS to pull data from a spreadsheet and +display the data. We'll explore how to import data from spreadsheets and export +data to spreadsheets. The following Material UI components will be tested: + +- ["Table"](#material-ui-table) is based on the core HTML TABLE element. + +- ["Data Grid"](#material-ui-data-grid) is a data grid for larger datasets. + +:::note pass + +The [ReactJS demo](/docs/demos/frontend/react) covers basic ReactJS concepts. +It should be perused before reading this demo. + +::: ## Integration Details [The "Frameworks" section](/docs/getting-started/installation/frameworks) covers installation in projects using Material UI. +After installing the SheetJS module in a ReactJS project, `import` statements +can load relevant parts of the library. + +```js +import { read, utils, writeFileXLSX } from 'xlsx'; +``` + ## Material UI Table -The `Table` component abstracts the `` element in HTML. `table_to_book` -can process a `ref` attached to the `Table` element: +The `Table` component abstracts the `
` element in HTML. -```tsx -import TableContainer from '@mui/material/TableContainer'; -import Table from '@mui/material/Table'; -// ... +### Importing Data + +Starting from a SheetJS worksheet object[^1], the `sheet_to_json` method[^2] +generates an array of row objects. + +In the [ReactJS "Array of Objects" demo](/docs/demos/frontend/react), the array +of objects is rendered by manually mapping over data. For example, starting from +the following spreadsheet and data: + +
+ +
SpreadsheetState
+ +![`pres.xlsx` data](pathname:///pres.png) + + + +```js +[ + { Name: "Bill Clinton", Index: 42 }, + { Name: "GeorgeW Bush", Index: 43 }, + { Name: "Barack Obama", Index: 44 }, + { Name: "Donald Trump", Index: 45 }, + { Name: "Joseph Biden", Index: 46 } +] +``` + +
+ +The HTML table elements map to MUI components: + +| HTML | MUI | +|:--------|:------------| +| `TABLE` | `Table` | +| `THEAD` | `TableHead` | +| `TBODY` | `TableBody` | +| `TR` | `TableRow` | +| `TD` | `TableCell` | + +The library requires a `TableContainer` container component. + +The following example JSX shows a table using HTML and using MUI components: + + + + +```jsx title="Example JSX for displaying arrays of objects" + + {/* The `thead` section includes the table header row */} + + {/* The `tbody` section includes the data rows */} + + {/* generate row (TR) for each president */} +// highlight-start + {pres.map(row => ( + + {/* Generate cell (TD) for name / index */} + + + + ))} +// highlight-end + +
NameIndex
{row.Name}{row.Index}
+``` + +
+ + +```jsx title="Example JSX for displaying arrays of objects" + + {/* The `TableHead` section includes the table header row */} + NameIndex + {/* The `TableBody` section includes the data rows */} + + {/* generate row (TableRow) for each president */} +// highlight-start + {pres.map((row, idx) => ( + + {/* Generate cell (TableCell) for name / index */} + {row.Name} + {row.Index} + + ))} +// highlight-end + +
+``` + +
+
+ +### Exporting Data + +The SheetJS `table_to_book` method[^3] can parse data from a DOM element. +The MUI `Table` element is really a HTML TABLE element under the hood. A `ref` +attached to the `Table` element can be processed by `table_to_book`. + +The following snippet uses the `writeFileXLSX` method[^4] to generate and +download a XLSX workbook: + +```tsx title="Skeleton Component for exporting a Material UI Table" // highlight-start import { utils, writeFileXLSX } from "xlsx"; import { useRef } from "react"; // highlight-end -// ... -export default function BasicTable() { +export default function MUITableSheetJSExport() { + /* This ref will be attached to the component */ // highlight-next-line const tbl = useRef(null); + + const xport = () => { + /* the .current field will be a TABLE element */ + const table_elt = tbl.current; + /* generate SheetJS workbook */ + // highlight-next-line + const wb = utils.table_to_book(table_elt); + /* export to XLSX */ + writeFileXLSX(wb, "SheetJSMaterialUI.xlsx"); + }; + return ( <> - - + + // highlight-next-line -
- {/* ... material ui table machinations ... */} -
+ {/* ... */}
<>); } @@ -52,8 +182,11 @@ export default function BasicTable() { :::note Tested Deployments -This demo was last run on 2023 December 04 against Material UI 5.14.19 paired -with Emotion 11.11.1 +This demo was tested in the following deployments: + +| Material UI | Emotion | Date | +|:------------|:----------|:-----------| +| `5.15.20` | `11.11.4` | 2024-06-12 | ::: @@ -67,7 +200,7 @@ cd sheetjs-mui 2) Install dependencies: {`\ -npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.14.19 @emotion/react@11.11.1 @emotion/styled@11.11.0`} +npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.15.20 @emotion/react@11.11.4 @emotion/styled@11.11.5`} 3) Download [`App.tsx`](pathname:///mui/table/App.tsx) and replace `src/App.tsx`. @@ -195,8 +328,11 @@ export default function App() { :::note Tested Deployments -This demo was last run on 2023 December 04 against MUI data grid 6.18.3 paired -with Emotion 11.11.1 +This demo was tested in the following deployments: + +| Data Grid | Emotion | Date | +|:----------|:----------|:-----------| +| `7.6.2` | `11.11.4` | 2024-06-12 | ::: @@ -210,7 +346,7 @@ cd sheetjs-muidg 2) Install dependencies: {`\ -npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid@6.18.3 @emotion/react@11.11.1 @emotion/styled@11.11.0`} +npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid@7.6.2 @emotion/react@11.11.4 @emotion/styled@11.11.5`} 3) Download [`App.tsx`](pathname:///mui/dg/App.tsx) and replace `src/App.tsx`. @@ -226,3 +362,8 @@ npm run dev ``` When the page loads, it will process https://docs.sheetjs.com/pres.numbers + +[^1]: See ["Sheet Objects"](/docs/csf/sheet) +[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output) +[^3]: See [`table_to_book` in "HTML" Utilities](/docs/api/utilities/html#create-new-sheet) +[^4]: See [`writeFileXLSX` in "Writing Files"](/docs/api/write-options) diff --git a/docz/docs/03-demos/30-cloud/12-azure.md b/docz/docs/03-demos/30-cloud/12-azure.md index 66a7869..10ea6e0 100644 --- a/docz/docs/03-demos/30-cloud/12-azure.md +++ b/docz/docs/03-demos/30-cloud/12-azure.md @@ -35,7 +35,7 @@ will be available in the future. :::note Tested Deployments -This demo was last tested on 2023 October 06. +This demo was last tested on 2024 June 12. ::: @@ -252,6 +252,17 @@ sudo npm i -g azure-functions-core-tools@4 --unsafe-perm true 3) Install [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) +
+ Installation Notes (click to show) + +On macOS, `azure-cli` can be installed from Homebrew: + +```bash +brew install azure-cli +``` + +
+ 4) Disable Azure CLI telemetry: ```bash @@ -268,6 +279,10 @@ cd SheetJSAzure func new --template httpTrigger --language JavaScript --name SheetJSAzure ``` +If prompted for a worker runtime, select `node` (Press 3) + +If prompted for a language, select `javascript` (Press 1) + :::danger pass When the demo was last tested, the stock TypeScript template did not work. @@ -333,19 +348,21 @@ Open in Excel or another spreadsheet editor to confirm the file is valid. 13) Sign into the [Azure Portal](https://portal.azure.com/#home) -14) Type "Function App" in the top search box and click "Function App" +14) Type "Function App" in the top search box and click "Function App": + +![Function App](pathname:///azure/functionapp.png) 15) Click "+ Create" 16) Select the following options: +- "Select a hosting option": "Consumption" + - Type a memorable "Function Name" ("sheetjsazure" when last tested) -- "Do you want to deploy code or container image?": select "Code" +- "Operating System": "Windows" -- "Runtime stack": select NodeJS - -- "Hosting options and plans": "Consumption (Serverless)" +- "Runtime stack": select `Node.js` 17) Click "Review + create", then click "Create" to create the function. @@ -359,7 +376,7 @@ When the resources are configured, the status will change to 18) Click "Go to Resource". -19) Take note of the URL from the table +19) Take note of the URL from the "Essentials" table. #### Deploy to Azure @@ -388,8 +405,24 @@ Functions in sheetjsazure: Take note of that URL. -#### Remote Test +:::danger pass +When this demo was last tested using the "Linux" operating system, the command +failed with a support error: + +``` +Azure Functions Core Tools does not support this deployment path. Please configure the app to deploy from a remote package using the steps here: https://aka.ms/deployfromurl +``` + +**This is a limitation of the Azure CLI tool with Linux functions!** + +Ensure that the selected operating system is "Windows". + +SheetJS libraries run in Linux-based functions. + +::: + +#### Remote Test 22) In a new terminal window, download https://docs.sheetjs.com/pres.numbers and make a POST request to the production server. Replace `FUNCTION_URL` with the @@ -501,7 +534,9 @@ requests and 2000 write requests per month. 1) Sign into the [Azure Portal](https://portal.azure.com/#home) -2) Type "Storage" in the top search box and click "Storage accounts" +2) Type "Storage" in the top search box and click "Storage accounts": + +![Storage Accounts](pathname:///azure/storageacct.png) 3) Click "+ Create" @@ -511,8 +546,6 @@ requests and 2000 write requests per month. - "Redundancy": select LRS (Locally-redundant storage) -- "Hosting options and plans": "Consumption (Serverless)" - 5) Click "Review", then click "Create" to create the storage. The page will display a status message @@ -527,15 +560,17 @@ When the resources are configured, the status will change to #### Access Keys -7) Click "Access keys" in the left sidebar (under "Security + networking") +7) Click "Access keys" in the left sidebar (under "Security + networking"). 8) Look for the "Connection string" title under "key1". In the row below the title, click "Show" to reveal the key. Click the copy icon or manually copy the key, storing it in a safe place. +![Connection string "Show" button](pathname:///azure/connstr.png) + #### Container Setup -9) Click "Containers" in the left sidebar. +9) Click "Containers" in the left sidebar (under "Data storage"). 10) Click "+ Container" @@ -617,7 +652,7 @@ S,h,e,e,t,J,S 21) Click on the name of the storage -22) In the middle column, click "Containers". It will be under "Data storage". +22) In the left sidebar, click "Containers". It will be under "Data storage". 23) Click on the name of the container in the table @@ -627,7 +662,9 @@ S,h,e,e,t,J,S 25) Click on the name `SheetJSBloblobber.xlsx`. -26) In the right pane, click "Download". +26) Click "Download" in the row below the file name: + +![Download link in the website](pathname:///azure/dl.png) The downloaded file is the raw file stored in Azure Blob Storage. To confirm it is valid, open the file in Excel or another spreadsheet editor. diff --git a/docz/static/azure/connstr.png b/docz/static/azure/connstr.png new file mode 100644 index 0000000..4a7194d Binary files /dev/null and b/docz/static/azure/connstr.png differ diff --git a/docz/static/azure/dl.png b/docz/static/azure/dl.png new file mode 100644 index 0000000..14908e4 Binary files /dev/null and b/docz/static/azure/dl.png differ diff --git a/docz/static/azure/functionapp.png b/docz/static/azure/functionapp.png new file mode 100644 index 0000000..7ae474e Binary files /dev/null and b/docz/static/azure/functionapp.png differ diff --git a/docz/static/azure/storageacct.png b/docz/static/azure/storageacct.png new file mode 100644 index 0000000..d4c92db Binary files /dev/null and b/docz/static/azure/storageacct.png differ diff --git a/docz/static/mui/table/App.tsx b/docz/static/mui/table/App.tsx index 3fdd824..36310a0 100644 --- a/docz/static/mui/table/App.tsx +++ b/docz/static/mui/table/App.tsx @@ -1,66 +1,48 @@ -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'; +import { TableContainer, Table, TableRow, TableCell, TableBody, TableHead } from '@mui/material'; +import { WorkBook, WorkSheet, read, utils, writeFileXLSX } from "xlsx"; +import { useRef, useState, useEffect } from "react"; -function createData( - name: string, - calories: number, - fat: number, - carbs: number, - protein: number, -) { - return { name, calories, fat, carbs, protein }; +import './App.css' + +interface President { + Name: string; + Index: number; } -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() { +function App() { const tbl = useRef(null); + const xport = () => { + const wb: WorkBook = utils.table_to_book(tbl.current); + writeFileXLSX(wb, "SheetJSMaterialUI.xlsx"); + }; + + const [pres, setPres] = useState([]); + useEffect(() => { + let active = true; + (async() => { + const ab: ArrayBuffer = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer(); + const wb: WorkBook = read(ab); + const ws: WorkSheet = wb.Sheets[wb.SheetNames[0]]; + const aoo: President[] = utils.sheet_to_json(ws); + if(active) setPres(aoo); + })(); + return () => { active = false }; + }, []); + return ( <> - - - - - - Dessert (100g serving) - Calories - Fat (g) - Carbs (g) - Protein (g) - - - - {rows.map((row) => ( - - - {row.name} - - {row.calories} - {row.fat} - {row.carbs} - {row.protein} - - ))} - -
-
+ + + NameIndex + + {pres.map((row, idx) => ( + + {row.Name} + {row.Index} + + ))} + +
); -} \ No newline at end of file +} + +export default App \ No newline at end of file