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 | ||||
| VBA | ||||
| Visicalc | ||||
| Chartsheet | ||||
| chartsheet | ||||
| Chartsheets | ||||
| chartsheets | ||||
| Dialogsheet | ||||
| dialogsheet | ||||
| Dialogsheets | ||||
| dialogsheets | ||||
| dBASE | ||||
| Macrosheet | ||||
| macrosheet | ||||
| Macrosheets | ||||
| macrosheets | ||||
| tooltip | ||||
| tooltips | ||||
| @ -192,3 +198,11 @@ vscode-data-preview | ||||
| axios | ||||
| superagent | ||||
| 
 | ||||
| LLC | ||||
| Bundlers | ||||
| JSON | ||||
| QPW | ||||
| XLML | ||||
| XLS | ||||
| XLSB | ||||
| XLSX | ||||
|  | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @ -10,6 +10,10 @@ build: | ||||
| serve: | ||||
| 	cd docs; python -mSimpleHTTPServer || python3 -mhttp.server; cd - | ||||
| 
 | ||||
| .PHONY: spell | ||||
| spell: | ||||
| 	npx spellchecker-cli -d .spelling -f 'docz/**/*.md*' | ||||
| 
 | ||||
| .PHONY: index | ||||
| index: readme ## Rebuild site
 | ||||
| 	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 | ||||
| 
 | ||||
| [The raw data is available in JSON form](https://theunitedstates.io/congress-legislators/executive.json). | ||||
| For convenience, it has been [mirrored here](https://sheetjs.com/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/data/executive.json) | ||||
| 
 | ||||
| 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 | ||||
| function Presidents() { return ( <button onClick={async () => { | ||||
|   /* 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(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
| @ -213,7 +213,7 @@ hosted (no `file:///` access). | ||||
| <script> | ||||
| (async() => { | ||||
|   /* 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(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
| @ -259,7 +259,7 @@ const XLSX = require("xlsx"); | ||||
| 
 | ||||
| (async() => { | ||||
|   /* 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(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
| @ -309,7 +309,7 @@ const axios = require("axios"); | ||||
| 
 | ||||
| (async() => { | ||||
|   /* fetch JSON data and parse */ | ||||
|   const url = "https://sheetjs.com/executive.json"; | ||||
|   const url = "https://sheetjs.com/data/executive.json"; | ||||
|   // highlight-next-line | ||||
|   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'; | ||||
| 
 | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -393,7 +393,7 @@ import * as fs from 'fs'; | ||||
| XLSX.set_fs(fs); | ||||
| 
 | ||||
| /* 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(); | ||||
| 
 | ||||
| /* 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. | ||||
| 
 | ||||
| <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(", ")})`; | ||||
|     })).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 [out, setOut] = React.useState(""); | ||||
|   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); | ||||
| ``` | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| :::caution | ||||
| @ -506,7 +506,7 @@ is strongly recommended to convert that array to a worksheet directly. | ||||
| 
 | ||||
| ```jsx live | ||||
| 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 [out, setOut] = React.useState(""); | ||||
|   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), | ||||
| 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> | ||||
| 
 | ||||
| @ -53,7 +53,7 @@ function SheetJSToTFJSCSV() { | ||||
|   const [output, setOutput] = React.useState(""); | ||||
|   const doit = React.useCallback(async () => { | ||||
|     /* 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(); | ||||
|     /* parse file and get first worksheet */ | ||||
|     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() { | ||||
|   // highlight-start | ||||
|   /* 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) */ | ||||
|   const carsDataAB = await carsDataResponse.arrayBuffer(); | ||||
|   /* parse */ | ||||
|  | ||||
| @ -124,7 +124,7 @@ import * as fs from 'fs'; | ||||
| XLSX.set_fs(fs); | ||||
| 
 | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -209,7 +209,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| 
 | ||||
| (async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -291,7 +291,7 @@ set_fs(fs); | ||||
| 
 | ||||
| (async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -369,7 +369,7 @@ import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| document.getElementById("vers").innerText = version; | ||||
| document.getElementById("xport").onclick = async() => { | ||||
|   /* 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(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
| @ -495,7 +495,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -589,7 +589,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -694,7 +694,7 @@ import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -910,7 +910,7 @@ SystemJS.config({ | ||||
| SystemJS.import('xlsx').then(async function(XLSX) { | ||||
| 
 | ||||
|   /* 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(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
| @ -1005,7 +1005,7 @@ interface President { | ||||
| 
 | ||||
| async function xport() { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -1108,7 +1108,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* filter for the Presidents */ | ||||
| @ -1268,7 +1268,7 @@ import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* 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(); | ||||
| 
 | ||||
| /* 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) | ||||
| - [`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) | ||||
| - [`Content Management and Static Sites`](./content) | ||||
| - [`Electron`](./desktop#electron) | ||||
| @ -50,7 +50,7 @@ The demo projects include small runnable examples and short explainers. | ||||
| - [`Excel JavaScript API`](./excel) | ||||
| - [`Headless Automation`](./headless) | ||||
| - [`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) | ||||
| - [`NoSQL and Unstructured Data Stores`](./nosql) | ||||
| - [`Legacy Internet Explorer`](./legacy#internet-explorer) | ||||
|  | ||||
| @ -17,7 +17,7 @@ require.config({ | ||||
| require(["xlsx"], function(XLSX) { | ||||
|   document.getElementById("xport").addEventListener("click", async() => { | ||||
|     /* 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(); | ||||
| 
 | ||||
|     /* filter for the Presidents */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user