forked from sheetjs/docs.sheetjs.com
azure
This commit is contained in:
parent
4b4bf7ff54
commit
541e0a8348
14
.spelling
14
.spelling
@ -23,12 +23,18 @@ SpreadsheetML
|
|||||||
Unhide
|
Unhide
|
||||||
VBA
|
VBA
|
||||||
Visicalc
|
Visicalc
|
||||||
|
Chartsheet
|
||||||
chartsheet
|
chartsheet
|
||||||
|
Chartsheets
|
||||||
chartsheets
|
chartsheets
|
||||||
|
Dialogsheet
|
||||||
dialogsheet
|
dialogsheet
|
||||||
|
Dialogsheets
|
||||||
dialogsheets
|
dialogsheets
|
||||||
dBASE
|
dBASE
|
||||||
|
Macrosheet
|
||||||
macrosheet
|
macrosheet
|
||||||
|
Macrosheets
|
||||||
macrosheets
|
macrosheets
|
||||||
tooltip
|
tooltip
|
||||||
tooltips
|
tooltips
|
||||||
@ -192,3 +198,11 @@ vscode-data-preview
|
|||||||
axios
|
axios
|
||||||
superagent
|
superagent
|
||||||
|
|
||||||
|
LLC
|
||||||
|
Bundlers
|
||||||
|
JSON
|
||||||
|
QPW
|
||||||
|
XLML
|
||||||
|
XLS
|
||||||
|
XLSB
|
||||||
|
XLSX
|
||||||
|
4
Makefile
4
Makefile
@ -10,6 +10,10 @@ build:
|
|||||||
serve:
|
serve:
|
||||||
cd docs; python -mSimpleHTTPServer || python3 -mhttp.server; cd -
|
cd docs; python -mSimpleHTTPServer || python3 -mhttp.server; cd -
|
||||||
|
|
||||||
|
.PHONY: spell
|
||||||
|
spell:
|
||||||
|
npx spellchecker-cli -d .spelling -f 'docz/**/*.md*'
|
||||||
|
|
||||||
.PHONY: index
|
.PHONY: index
|
||||||
index: readme ## Rebuild site
|
index: readme ## Rebuild site
|
||||||
sed -i .bak 's/](d/](https:\/\/github.com\/SheetJS\/SheetJS\/tree\/master\/d/g' README.md
|
sed -i .bak 's/](d/](https:\/\/github.com\/SheetJS\/SheetJS\/tree\/master\/d/g' README.md
|
||||||
|
@ -18,8 +18,8 @@ and birthdays. [Click here](#live-demo) to jump to the live demo
|
|||||||
|
|
||||||
### Raw Data
|
### Raw Data
|
||||||
|
|
||||||
[The raw data is available in JSON form](https://theunitedstates.io/congress-legislators/executive.json).
|
[The raw data is available in JSON form](https://theunitedstates.io/congress-legislators/data/executive.json).
|
||||||
For convenience, it has been [mirrored here](https://sheetjs.com/executive.json)
|
For convenience, it has been [mirrored here](https://sheetjs.com/data/executive.json)
|
||||||
|
|
||||||
The data result is an Array of objects. This is the data for John Adams:
|
The data result is an Array of objects. This is the data for John Adams:
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ XLSX.writeFile(workbook, "Presidents.xlsx");
|
|||||||
```jsx live
|
```jsx live
|
||||||
function Presidents() { return ( <button onClick={async () => {
|
function Presidents() { return ( <button onClick={async () => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -213,7 +213,7 @@ hosted (no `file:///` access).
|
|||||||
<script>
|
<script>
|
||||||
(async() => {
|
(async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -259,7 +259,7 @@ const XLSX = require("xlsx");
|
|||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -309,7 +309,7 @@ const axios = require("axios");
|
|||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
// highlight-next-line
|
// highlight-next-line
|
||||||
const raw_data = (await axios(url, {responseType: "json"})).data;
|
const raw_data = (await axios(url, {responseType: "json"})).data;
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ Save the following script to `snippet.ts` and run with
|
|||||||
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
||||||
|
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -393,7 +393,7 @@ import * as fs from 'fs';
|
|||||||
XLSX.set_fs(fs);
|
XLSX.set_fs(fs);
|
||||||
|
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
|
@ -101,7 +101,7 @@ await db.collection('coll').insertMany(aoo, { ordered: true });
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
This example will fetch <https://sheetjs.com/cd.xls>, scan the columns of the
|
This example will fetch <https://sheetjs.com/data/cd.xls>, scan the columns of the
|
||||||
first worksheet to determine data types, and generate 6 PostgreSQL statements.
|
first worksheet to determine data types, and generate 6 PostgreSQL statements.
|
||||||
|
|
||||||
<details><summary><b>Explanation</b> (click to show)</summary>
|
<details><summary><b>Explanation</b> (click to show)</summary>
|
||||||
@ -208,7 +208,7 @@ function SheetJSQLWriter() {
|
|||||||
if(fields.length) return `INSERT INTO \`${wsname}\` (${fields.join(", ")}) VALUES (${values.join(", ")})`;
|
if(fields.length) return `INSERT INTO \`${wsname}\` (${fields.join(", ")}) VALUES (${values.join(", ")})`;
|
||||||
})).filter(x => x).slice(0, 6);
|
})).filter(x => x).slice(0, 6);
|
||||||
}
|
}
|
||||||
const [url, setUrl] = React.useState("https://sheetjs.com/cd.xls");
|
const [url, setUrl] = React.useState("https://sheetjs.com/data/cd.xls");
|
||||||
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
|
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
|
||||||
const [out, setOut] = React.useState("");
|
const [out, setOut] = React.useState("");
|
||||||
const xport = React.useCallback(async() => {
|
const xport = React.useCallback(async() => {
|
||||||
@ -494,7 +494,7 @@ for(var i = 0; i < localStorage.length; ++i) aoo.push(JSON.parse(localStorage.ge
|
|||||||
const ws = XLSX.utils.json_to_sheet(aoo);
|
const ws = XLSX.utils.json_to_sheet(aoo);
|
||||||
```
|
```
|
||||||
|
|
||||||
This example will fetch <https://sheetjs.com/cd.xls>, fill `localStorage` with
|
This example will fetch <https://sheetjs.com/data/cd.xls>, fill `localStorage` with
|
||||||
rows, then generate a worksheet from the rows and write to a new file.
|
rows, then generate a worksheet from the rows and write to a new file.
|
||||||
|
|
||||||
:::caution
|
:::caution
|
||||||
@ -506,7 +506,7 @@ is strongly recommended to convert that array to a worksheet directly.
|
|||||||
|
|
||||||
```jsx live
|
```jsx live
|
||||||
function SheetJStorage() {
|
function SheetJStorage() {
|
||||||
const [url, setUrl] = React.useState("https://sheetjs.com/cd.xls");
|
const [url, setUrl] = React.useState("https://sheetjs.com/data/cd.xls");
|
||||||
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
|
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
|
||||||
const [out, setOut] = React.useState("");
|
const [out, setOut] = React.useState("");
|
||||||
const xport = React.useCallback(async() => {
|
const xport = React.useCallback(async() => {
|
||||||
|
@ -44,7 +44,7 @@ function worksheet_to_csv_url(worksheet) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
[This demo mirrors TFjs docs](https://js.tensorflow.org/api/latest/#data.csv),
|
[This demo mirrors TFjs docs](https://js.tensorflow.org/api/latest/#data.csv),
|
||||||
fetching [an XLSX export of the example dataset](https://sheetjs.com/bht.xlsx).
|
fetching [an XLSX export of the example dataset](https://sheetjs.com/data/bht.xlsx).
|
||||||
|
|
||||||
<details><summary><b>TF CSV Demo using XLSX files</b> (click to show)</summary>
|
<details><summary><b>TF CSV Demo using XLSX files</b> (click to show)</summary>
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ function SheetJSToTFJSCSV() {
|
|||||||
const [output, setOutput] = React.useState("");
|
const [output, setOutput] = React.useState("");
|
||||||
const doit = React.useCallback(async () => {
|
const doit = React.useCallback(async () => {
|
||||||
/* fetch file */
|
/* fetch file */
|
||||||
const f = await fetch("https://sheetjs.com/bht.xlsx");
|
const f = await fetch("https://sheetjs.com/data/bht.xlsx");
|
||||||
const ab = await f.arrayBuffer();
|
const ab = await f.arrayBuffer();
|
||||||
/* parse file and get first worksheet */
|
/* parse file and get first worksheet */
|
||||||
const wb = XLSX.read(ab);
|
const wb = XLSX.read(ab);
|
||||||
@ -125,7 +125,7 @@ loads data from a JSON file:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
In real use cases, data is stored in [spreadsheets](https://sheetjs.com/cd.xls)
|
In real use cases, data is stored in [spreadsheets](https://sheetjs.com/data/cd.xls)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -140,7 +140,7 @@ from the official example are highlighted below:
|
|||||||
async function getData() {
|
async function getData() {
|
||||||
// highlight-start
|
// highlight-start
|
||||||
/* fetch file */
|
/* fetch file */
|
||||||
const carsDataResponse = await fetch('https://sheetjs.com/cd.xls');
|
const carsDataResponse = await fetch('https://sheetjs.com/data/cd.xls');
|
||||||
/* get file data (ArrayBuffer) */
|
/* get file data (ArrayBuffer) */
|
||||||
const carsDataAB = await carsDataResponse.arrayBuffer();
|
const carsDataAB = await carsDataResponse.arrayBuffer();
|
||||||
/* parse */
|
/* parse */
|
||||||
|
@ -124,7 +124,7 @@ import * as fs from 'fs';
|
|||||||
XLSX.set_fs(fs);
|
XLSX.set_fs(fs);
|
||||||
|
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -209,7 +209,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs';
|
|||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -291,7 +291,7 @@ set_fs(fs);
|
|||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -369,7 +369,7 @@ import { utils, version, writeFileXLSX } from 'xlsx';
|
|||||||
document.getElementById("vers").innerText = version;
|
document.getElementById("vers").innerText = version;
|
||||||
document.getElementById("xport").onclick = async() => {
|
document.getElementById("xport").onclick = async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -495,7 +495,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs';
|
|||||||
|
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -589,7 +589,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs';
|
|||||||
|
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -694,7 +694,7 @@ import { utils, version, writeFileXLSX } from 'xlsx';
|
|||||||
|
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -910,7 +910,7 @@ SystemJS.config({
|
|||||||
SystemJS.import('xlsx').then(async function(XLSX) {
|
SystemJS.import('xlsx').then(async function(XLSX) {
|
||||||
|
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -1005,7 +1005,7 @@ interface President {
|
|||||||
|
|
||||||
async function xport() {
|
async function xport() {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data: President[] = await (await fetch(url)).json();
|
const raw_data: President[] = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -1108,7 +1108,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs';
|
|||||||
|
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
@ -1268,7 +1268,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs';
|
|||||||
|
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
|
277
docz/docs/03-demos/25-azure.md
Normal file
277
docz/docs/03-demos/25-azure.md
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
---
|
||||||
|
sidebar_position: 25
|
||||||
|
title: Azure Cloud Services
|
||||||
|
---
|
||||||
|
|
||||||
|
Azure is a Cloud Services platform which includes traditional virtual machine
|
||||||
|
support, "Serverless Functions", cloud storage and much more.
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Azure iterates quickly and there is no guarantee that the referenced services
|
||||||
|
will be available in the future.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
This demo focuses on two key offerings: cloud storage ("Azure Blob Storage")
|
||||||
|
and the "Serverless Function" platform ("Azure Functions").
|
||||||
|
|
||||||
|
## Azure Functions
|
||||||
|
|
||||||
|
This discussion focuses on the "HTTP Trigger" function type.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
To enable binary data processing, a setting must be changed in `function.json`:
|
||||||
|
|
||||||
|
```json title="function.json"
|
||||||
|
{
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"type": "httpTrigger",
|
||||||
|
"direction": "in",
|
||||||
|
//highlight-next-line
|
||||||
|
"dataType": "binary",
|
||||||
|
"name": "req",
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Reading Data
|
||||||
|
|
||||||
|
`formidable` expects a stream and Azure does not present one. It can be made:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const XLSX = require('xlsx');
|
||||||
|
const formidable = require('formidable');
|
||||||
|
const Readable = require('stream').Readable;
|
||||||
|
|
||||||
|
/* formidable expects the request object to be a stream */
|
||||||
|
const streamify = (req) => {
|
||||||
|
if(typeof req.on !== 'undefined') return req;
|
||||||
|
const s = new Readable();
|
||||||
|
s._read = ()=>{};
|
||||||
|
s.push(Buffer.from(req.body));
|
||||||
|
s.push(null);
|
||||||
|
Object.assign(s, req);
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (context, req) => {
|
||||||
|
const form = new formidable.IncomingForm();
|
||||||
|
form.parse(streamify(req), (err, fields, files) => {
|
||||||
|
/* grab the first file */
|
||||||
|
var f = files["upload"];
|
||||||
|
if(!f) {
|
||||||
|
context.res = { status: 400, body: "Must submit a file for processing!" };
|
||||||
|
} else {
|
||||||
|
/* file is stored in a temp directory, so we can point to that and read it */
|
||||||
|
const wb = XLSX.read(f.filepath, {type:"file"});
|
||||||
|
|
||||||
|
/* generate CSV from first sheet */
|
||||||
|
const csv = XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
|
||||||
|
context.res = { status: 200, body: csv };
|
||||||
|
}
|
||||||
|
context.done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Writing Data
|
||||||
|
|
||||||
|
The `body` property can be a Buffer, like those generated by `XLSX.write`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const XLSX = require('xlsx');
|
||||||
|
module.exports = (context, req) => {
|
||||||
|
// generate XLSX file in a Buffer
|
||||||
|
var ws = XLSX.utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
|
||||||
|
var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Data");
|
||||||
|
// highlight-next-line
|
||||||
|
var buf = XLSX.write(wb, {type: "buffer", bookType: "xlsx"});
|
||||||
|
|
||||||
|
// Set the body and Content-Disposition header
|
||||||
|
// highlight-start
|
||||||
|
context.res = {
|
||||||
|
status: 200,
|
||||||
|
headers: { "Content-Disposition": `attachment; filename="SheetJSAzure.xlsx";` },
|
||||||
|
body: buf
|
||||||
|
};
|
||||||
|
// highlight-end
|
||||||
|
context.done();
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Demo
|
||||||
|
|
||||||
|
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||||
|
|
||||||
|
0) Review the quick start for JavaScript on Azure Functions. This involves
|
||||||
|
installing the Azure Functions Core Tools and other dependencies.
|
||||||
|
|
||||||
|
1) Create a new project and install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
func init sheetjs-azure --worker-runtime node --language javascript
|
||||||
|
cd sheetjs-azure
|
||||||
|
npm i
|
||||||
|
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz formidable
|
||||||
|
```
|
||||||
|
|
||||||
|
2) Create a new "HTTP Trigger" function:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
func new --template "Http Trigger" --name SheetJSAzure
|
||||||
|
```
|
||||||
|
|
||||||
|
3) Edit `SheetJSAzure/function.json` to add the `dataType: "binary"` property:
|
||||||
|
|
||||||
|
```js title="SheetJSAzure/function.json"
|
||||||
|
"direction": "in",
|
||||||
|
// highlight-next-line
|
||||||
|
"dataType": "binary",
|
||||||
|
"name": "req",
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Replace `SheetJSAzure/index.js` with the following:
|
||||||
|
|
||||||
|
```js title="SheetJSAzure/index.js"
|
||||||
|
/* sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||||
|
const XLSX = require('xlsx');
|
||||||
|
const formidable = require('formidable');
|
||||||
|
const Readable = require('stream').Readable;
|
||||||
|
|
||||||
|
/* formidable expects the request object to be a stream */
|
||||||
|
const streamify = (req) => {
|
||||||
|
if(typeof req.on !== 'undefined') return req;
|
||||||
|
const s = new Readable();
|
||||||
|
s._read = ()=>{};
|
||||||
|
s.push(Buffer.from(req.body));
|
||||||
|
s.push(null);
|
||||||
|
Object.assign(s, req);
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (context, req) => {
|
||||||
|
if(req.method == "POST") {
|
||||||
|
const form = new formidable.IncomingForm();
|
||||||
|
form.parse(streamify(req), (err, fields, files) => {
|
||||||
|
/* grab the first file */
|
||||||
|
var f = files["upload"];
|
||||||
|
if(!f) {
|
||||||
|
context.res = { status: 400, body: "Must submit a file for processing!" };
|
||||||
|
} else {
|
||||||
|
/* file is stored in a temp directory, so we can point to that and read it */
|
||||||
|
const wb = XLSX.read(f.filepath, {type:"file"});
|
||||||
|
|
||||||
|
/* generate CSV from first sheet */
|
||||||
|
const csv = XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
|
||||||
|
context.res = { status: 200, body: csv };
|
||||||
|
}
|
||||||
|
context.done();
|
||||||
|
});
|
||||||
|
} else if(req.method == "GET") {
|
||||||
|
var ws = XLSX.utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
|
||||||
|
var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Data");
|
||||||
|
var buf = XLSX.write(wb, {type: "buffer", bookType: "xlsx"});
|
||||||
|
context.res = {
|
||||||
|
status: 200,
|
||||||
|
headers: { "Content-Disposition": `attachment; filename="SheetJSAzure.xlsx";` },
|
||||||
|
body: buf
|
||||||
|
};
|
||||||
|
context.done();
|
||||||
|
} else {
|
||||||
|
context.res = { status: 500, body: `Unsupported method ${req.method}` };
|
||||||
|
context.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
5) Test locally with `npm start`
|
||||||
|
|
||||||
|
To test uploads, download <https://sheetjs.com/pres.numbers> and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -F "upload=@pres.numbers" http://localhost:7071/api/SheetJSAzure
|
||||||
|
```
|
||||||
|
|
||||||
|
To test downloads, access http://localhost:7071/api/SheetJSAzure and download
|
||||||
|
the generated file. Confirm it is a valid file.
|
||||||
|
|
||||||
|
6) Deploy to Azure. Replace `NAME_OF_FUNCTION_APP` with the name:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
func azure functionapp publish NAME_OF_FUNCTION_APP
|
||||||
|
```
|
||||||
|
|
||||||
|
Get the function url and test using the same sequence as in step 5.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Azure Blob Storage
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
This was tested on 2022 August 21.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The main module for Azure Blob Storage is `@azure/storage-blob`. This example
|
||||||
|
was tested using the "Connection String" authentication method. The strings
|
||||||
|
are found in the Azure Portal under "Access Keys" for the storage account.
|
||||||
|
|
||||||
|
### Reading Data
|
||||||
|
|
||||||
|
The `BlobClient#download` method returns a Stream. After collecting into a
|
||||||
|
Buffer, `XLSX.read` can parse the data:
|
||||||
|
|
||||||
|
```js title="SheetJSReadFromAzure.mjs"
|
||||||
|
import { BlobServiceClient } from "@azure/storage-blob";
|
||||||
|
import { read, utils } from "xlsx";
|
||||||
|
|
||||||
|
/* replace these constants */
|
||||||
|
const connStr = "<REPLACE WITH CONNECTION STRING>";
|
||||||
|
const containerName = "<REPLACE WITH CONTAINER NAME>";
|
||||||
|
const blobName = "<REPLACE WITH BLOB NAME>";
|
||||||
|
|
||||||
|
/* get a readable stream*/
|
||||||
|
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
|
||||||
|
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||||
|
const blobClient = containerClient.getBlobClient(blobName);
|
||||||
|
const response = (await blobClient.download()).readableStreamBody;
|
||||||
|
|
||||||
|
/* collect data into a Buffer */
|
||||||
|
const bufs = [];
|
||||||
|
for await(const buf of response) bufs.push(buf);
|
||||||
|
const downloaded = Buffer.concat(bufs);
|
||||||
|
|
||||||
|
/* parse downloaded buffer */
|
||||||
|
const wb = read(downloaded);
|
||||||
|
/* print first worksheet */
|
||||||
|
console.log(utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Writing Data
|
||||||
|
|
||||||
|
`BlockBlobClient#upload` directly accepts a Buffer:
|
||||||
|
|
||||||
|
```js title="SheetJSWriteToAzure.mjs"
|
||||||
|
import { BlobServiceClient } from "@azure/storage-blob";
|
||||||
|
import { read, utils } from "xlsx";
|
||||||
|
|
||||||
|
/* replace these constants */
|
||||||
|
const connStr = "<REPLACE WITH CONNECTION STRING>";
|
||||||
|
const containerName = "<REPLACE WITH CONTAINER NAME>";
|
||||||
|
const blobName = "<REPLACE WITH BLOB NAME>";
|
||||||
|
|
||||||
|
/* Create a simple workbook and write XLSX to buffer */
|
||||||
|
const ws = utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
|
||||||
|
const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "Sheet1");
|
||||||
|
const buf = write(wb, {type: "buffer", bookType: "xlsx"});
|
||||||
|
|
||||||
|
/* upload buffer */
|
||||||
|
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
|
||||||
|
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||||
|
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
|
||||||
|
const uploadBlobResponse = await blockBlobClient.upload(buf, buf.length);
|
||||||
|
```
|
@ -36,7 +36,7 @@ The demo projects include small runnable examples and short explainers.
|
|||||||
|
|
||||||
- [`Command-Line Tools`](./cli)
|
- [`Command-Line Tools`](./cli)
|
||||||
- [`iOS and Android Mobile Applications`](./mobile)
|
- [`iOS and Android Mobile Applications`](./mobile)
|
||||||
- [`NodeJS Server-Side Processing`](https://github.com/SheetJS/SheetJS/tree/master/demos/server/)
|
- [`NodeJS Server-Side Processing`](./server#nodejs)
|
||||||
- [`Deno Server-Side Processing`](./server#deno)
|
- [`Deno Server-Side Processing`](./server#deno)
|
||||||
- [`Content Management and Static Sites`](./content)
|
- [`Content Management and Static Sites`](./content)
|
||||||
- [`Electron`](./desktop#electron)
|
- [`Electron`](./desktop#electron)
|
||||||
@ -50,7 +50,7 @@ The demo projects include small runnable examples and short explainers.
|
|||||||
- [`Excel JavaScript API`](./excel)
|
- [`Excel JavaScript API`](./excel)
|
||||||
- [`Headless Automation`](./headless)
|
- [`Headless Automation`](./headless)
|
||||||
- [`Other JavaScript Engines`](./engines)
|
- [`Other JavaScript Engines`](./engines)
|
||||||
- [`"serverless" functions`](https://github.com/SheetJS/SheetJS/tree/master/demos/function/)
|
- [`Azure Functions and Storage`](./azure)
|
||||||
- [`Databases and Structured Data Stores`](./database)
|
- [`Databases and Structured Data Stores`](./database)
|
||||||
- [`NoSQL and Unstructured Data Stores`](./nosql)
|
- [`NoSQL and Unstructured Data Stores`](./nosql)
|
||||||
- [`Legacy Internet Explorer`](./legacy#internet-explorer)
|
- [`Legacy Internet Explorer`](./legacy#internet-explorer)
|
||||||
|
@ -17,7 +17,7 @@ require.config({
|
|||||||
require(["xlsx"], function(XLSX) {
|
require(["xlsx"], function(XLSX) {
|
||||||
document.getElementById("xport").addEventListener("click", async() => {
|
document.getElementById("xport").addEventListener("click", async() => {
|
||||||
/* fetch JSON data and parse */
|
/* fetch JSON data and parse */
|
||||||
const url = "https://sheetjs.com/executive.json";
|
const url = "https://sheetjs.com/data/executive.json";
|
||||||
const raw_data = await (await fetch(url)).json();
|
const raw_data = await (await fetch(url)).json();
|
||||||
|
|
||||||
/* filter for the Presidents */
|
/* filter for the Presidents */
|
||||||
|
Loading…
Reference in New Issue
Block a user