Azure Cloud demo refresh
This commit is contained in:
parent
9c0d1bc162
commit
9d9478e6e5
@ -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 `<table>` element in HTML. `table_to_book`
|
||||
can process a `ref` attached to the `Table` element:
|
||||
The `Table` component abstracts the `<table>` 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:
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Spreadsheet</th><th>State</th></tr></thead>
|
||||
<tbody><tr><td>
|
||||
|
||||
![`pres.xlsx` data](pathname:///pres.png)
|
||||
|
||||
</td><td>
|
||||
|
||||
```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 }
|
||||
]
|
||||
```
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
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:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="ReactJS" label="ReactJS">
|
||||
|
||||
```jsx title="Example JSX for displaying arrays of objects"
|
||||
<table>
|
||||
{/* The `thead` section includes the table header row */}
|
||||
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
||||
{/* The `tbody` section includes the data rows */}
|
||||
<tbody>
|
||||
{/* generate row (TR) for each president */}
|
||||
// highlight-start
|
||||
{pres.map(row => (
|
||||
<tr>
|
||||
{/* Generate cell (TD) for name / index */}
|
||||
<td>{row.Name}</td>
|
||||
<td>{row.Index}</td>
|
||||
</tr>
|
||||
))}
|
||||
// highlight-end
|
||||
</tbody>
|
||||
</table>
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="MUI" label="Material UI">
|
||||
|
||||
```jsx title="Example JSX for displaying arrays of objects"
|
||||
<TableContainer><Table>
|
||||
{/* The `TableHead` section includes the table header row */}
|
||||
<TableHead><TableRow><TableCell>Name</TableCell><TableCell>Index</TableCell></TableRow></TableHead>
|
||||
{/* The `TableBody` section includes the data rows */}
|
||||
<TableBody>
|
||||
{/* generate row (TableRow) for each president */}
|
||||
// highlight-start
|
||||
{pres.map((row, idx) => (
|
||||
<TableRow key={idx}>
|
||||
{/* Generate cell (TableCell) for name / index */}
|
||||
<TableCell>{row.Name}</TableCell>
|
||||
<TableCell>{row.Index}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
// highlight-end
|
||||
</TableBody>
|
||||
</Table></TableContainer>
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 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 <Table> component */
|
||||
// highlight-next-line
|
||||
const tbl = useRef<HTMLTableElement>(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 ( <>
|
||||
<button onClick={() => {
|
||||
// highlight-next-line
|
||||
const wb = utils.table_to_book(tbl.current);
|
||||
writeFileXLSX(wb, "SheetJSMaterialUI.xlsx");
|
||||
}}>Export</button>
|
||||
<TableContainer {...}>
|
||||
<button onClick={xport}>Export</button>
|
||||
<TableContainer>
|
||||
// highlight-next-line
|
||||
<Table {...} ref={tbl}>
|
||||
{/* ... material ui table machinations ... */}
|
||||
</Table>
|
||||
<Table ref={tbl}>{/* ... */}</Table>
|
||||
</TableContainer>
|
||||
<>);
|
||||
}
|
||||
@ -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:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
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`}
|
||||
</CodeBlock>
|
||||
|
||||
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:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
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`}
|
||||
</CodeBlock>
|
||||
|
||||
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)
|
||||
|
@ -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)
|
||||
|
||||
<details>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
|
||||
On macOS, `azure-cli` can be installed from Homebrew:
|
||||
|
||||
```bash
|
||||
brew install azure-cli
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
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 <kbd>3</kbd>)
|
||||
|
||||
If prompted for a language, select `javascript` (Press <kbd>1</kbd>)
|
||||
|
||||
:::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.
|
||||
|
BIN
docz/static/azure/connstr.png
Normal file
BIN
docz/static/azure/connstr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
docz/static/azure/dl.png
Normal file
BIN
docz/static/azure/dl.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
BIN
docz/static/azure/functionapp.png
Normal file
BIN
docz/static/azure/functionapp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
docz/static/azure/storageacct.png
Normal file
BIN
docz/static/azure/storageacct.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
@ -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<HTMLTableElement>(null);
|
||||
const xport = () => {
|
||||
const wb: WorkBook = utils.table_to_book(tbl.current);
|
||||
writeFileXLSX(wb, "SheetJSMaterialUI.xlsx");
|
||||
};
|
||||
|
||||
const [pres, setPres] = useState<President[]>([]);
|
||||
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<President>(ws);
|
||||
if(active) setPres(aoo);
|
||||
})();
|
||||
return () => { active = false };
|
||||
}, []);
|
||||
|
||||
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>
|
||||
<button onClick={xport}>Export</button>
|
||||
<TableContainer><Table ref={tbl}>
|
||||
<TableHead><TableRow><TableCell>Name</TableCell><TableCell>Index</TableCell></TableRow></TableHead>
|
||||
<TableBody>
|
||||
{pres.map((row, idx) => (
|
||||
<TableRow key={idx}>
|
||||
<TableCell>{row.Name}</TableCell>
|
||||
<TableCell>{row.Index}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table></TableContainer>
|
||||
</> );
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
Loading…
Reference in New Issue
Block a user