forked from sheetjs/docs.sheetjs.com
		
	localstorage
This commit is contained in:
		
							parent
							
								
									d54a1e4ee0
								
							
						
					
					
						commit
						dbe0554b9b
					
				| @ -4,8 +4,10 @@ pagination_prev: demos/desktop/index | ||||
| pagination_next: demos/grid | ||||
| --- | ||||
| 
 | ||||
| At the time of writing (2023 February 15), Airtable recommends Personal Access | ||||
| Tokens for interacting with the official API. | ||||
| Airtable recommends Personal Access Tokens for interacting with their API. When | ||||
| fetching data from the API, the result will include an array of row objects that | ||||
| can be converted to a worksheet with `XLSX.utils.json_to_sheet`. The API methods | ||||
| to write data will accept row objects generated by `XLSX.utils.sheet_to_json`. | ||||
| 
 | ||||
| ## NodeJS Integration | ||||
| 
 | ||||
| @ -76,6 +78,13 @@ async function airtable_load_worksheet(table, worksheet) { | ||||
| 
 | ||||
| ## Complete Example | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on 2023 February 15.  At the time, it was possible to | ||||
| create a free account with API access. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 0) Create a free Airtable account. | ||||
| 
 | ||||
| ### Personal Access Token | ||||
|  | ||||
| @ -9,23 +9,80 @@ sidebar_custom_props: | ||||
| The Storage API, encompassing `localStorage` and `sessionStorage`, describes | ||||
| simple key-value stores that only support string values and keys. | ||||
| 
 | ||||
| Arrays of objects can be stored using `JSON.stringify` using row index as key: | ||||
| This demo covers two common use patterns: | ||||
| 
 | ||||
| - "Row Objects" shows a simple convention for loading and storing row objects | ||||
| - "Simple Strings" discusses how to persist and recover a raw Storage | ||||
| 
 | ||||
| ## Row Objects | ||||
| 
 | ||||
| Consider the following array of objects of data: | ||||
| 
 | ||||
| ```js | ||||
| const aoo = XLSX.utils.sheet_to_json(ws); | ||||
| for(var i = 0; i < aoo.length; ++i) localStorage.setItem(i, JSON.stringify(aoo[i])); | ||||
| [ | ||||
|   { Name: "Barack Obama", Index: 44 }, | ||||
|   { Name: "Donald Trump", Index: 45 }, | ||||
|   { Name: "Joseph Biden", Index: 46 } | ||||
| ] | ||||
| ``` | ||||
| 
 | ||||
| Recovering the array of objects is possible by using `JSON.parse`: | ||||
| Storage API expects values to be strings. The simplest approach is to stringify | ||||
| row objects using `JSON.stringify` and store using the row index as a key: | ||||
| 
 | ||||
| | Key | Value                                | | ||||
| |:---:|:-------------------------------------| | ||||
| |  0  | `{"Name":"Barack Obama","Index":44}` | | ||||
| |  1  | `{"Name":"Donald Trump","Index":45}` | | ||||
| |  2  | `{"Name":"Joseph Biden","Index":46}` | | ||||
| 
 | ||||
| #### Importing Data | ||||
| 
 | ||||
| Starting from a worksheet, `XLSX.utils.sheet_to_json` generates an array of row | ||||
| objects.  `localStorage.setItem` will store data in Local Storage: | ||||
| 
 | ||||
| ```js | ||||
| const aoo = []; | ||||
| for(var i = 0; i < localStorage.length; ++i) aoo.push(JSON.parse(localStorage.getItem(i))); | ||||
| const ws = XLSX.utils.json_to_sheet(aoo); | ||||
| function sheet_to_localStorage(worksheet) { | ||||
|   const aoo = XLSX.utils.sheet_to_json(worksheet); | ||||
|   for(let i = 0; i < aoo.length; ++i) { | ||||
|     localStorage.setItem(i, JSON.stringify(aoo[i])); | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 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. | ||||
| #### Exporting Data | ||||
| 
 | ||||
| `localStorage.length` returns the total number of entries. A simple `for` loop | ||||
| can cover the keys (integers from `0` to `localStorage.length - 1` inclusive) | ||||
| 
 | ||||
| `localStorage.getItem` will load the stringified data from the Local Storage. A | ||||
| new array of objects can be constructed by using `JSON.parse` and pushing to an | ||||
| array.  `XLSX.utils.json_to_sheet` can create a new worksheet from that array: | ||||
| 
 | ||||
| ```js | ||||
| function localStorage_to_sheet() { | ||||
|   const aoo = []; | ||||
|   for(let i = 0; i < localStorage.length; ++i) { | ||||
|     aoo.push(JSON.parse(localStorage.getItem(i))); | ||||
|   } | ||||
|   return XLSX.utils.json_to_sheet(aoo); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ### Live Demo | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on 2023 February 26. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| This example will fetch <https://sheetjs.com/pres.numbers>, fill `localStorage` | ||||
| with rows, then generate a worksheet from the rows and write to a new file. | ||||
| 
 | ||||
| After saving the exported file, the Local Storage can be inspected in the | ||||
| "Local Storage" section of the "Application" Tab of Developer Tools: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| @ -36,14 +93,13 @@ is strongly recommended to convert that array to a worksheet directly. | ||||
| 
 | ||||
| ```jsx live | ||||
| function SheetJStorage() { | ||||
|   const [url, setUrl] = React.useState("https://sheetjs.com/data/cd.xls"); | ||||
|   const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers"); | ||||
|   const set_url = React.useCallback((evt) => setUrl(evt.target.value)); | ||||
|   const [out, setOut] = React.useState(""); | ||||
|   const xport = React.useCallback(async() => { | ||||
|     // get first worksheet data as array of objects | ||||
|     const ab = await (await fetch(url)).arrayBuffer(); | ||||
|     const wb = XLSX.read(ab), wsname = wb.SheetNames[0]; | ||||
|     const aoo = XLSX.utils.sheet_to_json(wb.Sheets[wsname]); | ||||
|     const wb = XLSX.read(await (await fetch(url)).arrayBuffer()); | ||||
|     const aoo = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); | ||||
| 
 | ||||
|     // reset and populate localStorage | ||||
|     localStorage.clear(); | ||||
| @ -65,9 +121,59 @@ function SheetJStorage() { | ||||
|     XLSX.writeFile(new_wb, "SheetJStorage.xlsx"); | ||||
|   }); | ||||
| 
 | ||||
|   return ( <> {out && (<><a href={url}>{url}</a><pre>{out}</pre></>)} | ||||
|   return ( <> | ||||
|     {out && (<><a href={url}>{url}</a><pre>{out}</pre></>)} | ||||
|     <b>URL: </b><input type="text" value={url} onChange={set_url} size="50"/> | ||||
|     <br/><button onClick={xport}><b>Fetch!</b></button> | ||||
|   </> ); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Simple Strings | ||||
| 
 | ||||
| The ["Row Objects" approach](#row-objects) is strongly recommended when trying | ||||
| to store or recover arrays of row objects. | ||||
| 
 | ||||
| When the goal is to save an existing Storage, the general representation is an | ||||
| array of pairs.  Consider the following data in Local Storage: | ||||
| 
 | ||||
| | Key | Value     | | ||||
| |:---:|:----------| | ||||
| | "b" | "Logical" | | ||||
| | "n" | "Numeric" | | ||||
| | "s" | "Textual"  | | ||||
| 
 | ||||
| The natural representation is an array of arrays: | ||||
| 
 | ||||
| ```js | ||||
| [ | ||||
|   [ "b", "Logical" ], | ||||
|   [ "n", "Numeric" ], | ||||
|   [ "s", "Textual" ] | ||||
| ] | ||||
| ``` | ||||
| 
 | ||||
| #### Exporting Storage | ||||
| 
 | ||||
| In modern browsers, `Object.entries` will generate an array of key/value pairs. | ||||
| `XLSX.utils.aoa_to_sheet` will interpret that array as a worksheet with 2 cols: | ||||
| 
 | ||||
| ```js | ||||
| function localStorage_to_ws() { | ||||
|   const aoa = Object.entries(localStorage); | ||||
|   return XLSX.utils.aoa_to_sheet(aoa); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| #### Importing Storage | ||||
| 
 | ||||
| In the other direction, the worksheet is assumed to store keys in column A and | ||||
| values in column B.  `XLSX.utils.sheet_to_json` with the `header: 1` option | ||||
| will generate key/value pairs that can be assigned to a storage: | ||||
| 
 | ||||
| ```js | ||||
| function ws_to_localStorage(ws) { | ||||
|   const aoa = XLSX.utils.sheet_to_json(ws, { header: 1 }); | ||||
|   aoa.forEach(([key, val]) => localStorage.setItem(key, val)); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| @ -125,23 +125,34 @@ importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js | ||||
| 
 | ||||
| For production use, it is highly encouraged to download and host the script. | ||||
| 
 | ||||
| <details><summary><b>ECMAScript Module Support</b> (click to show)</summary> | ||||
| <details open><summary><b>ECMAScript Module Support</b> (click to hide)</summary> | ||||
| 
 | ||||
| :::note Browser Compatibility | ||||
| 
 | ||||
| ESM is supported in Web Workers in the Chromium family of browsers (including | ||||
| Chrome and Edge) as well as in browsers powered by WebKit (including Safari). | ||||
| 
 | ||||
| For support in legacy browsers like Firefox, `importScripts` should be used. | ||||
| For legacy browsers like Firefox and IE, `importScripts` should be used. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Browser ESM imports require a complete URL including the `.mjs` extension: | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from "https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs"; | ||||
| ``` | ||||
| 
 | ||||
| When using modules, the script must be served with the correct MIME type and the | ||||
| Worker constructor must set the `type` option: | ||||
| When using Worker ESM, the Worker constructor must set the `type` option: | ||||
| 
 | ||||
| ```js | ||||
| const worker = new Worker( | ||||
|   url_to_worker_script, | ||||
|   // highlight-next-line | ||||
|   { type: "module" } // second argument to Worker constructor | ||||
| ); | ||||
| ``` | ||||
| 
 | ||||
| Inline workers additionally require the Blob MIME type `text/javascript`: | ||||
| 
 | ||||
| ```js | ||||
| const worker_code = `\ | ||||
| @ -158,13 +169,15 @@ const worker = new Worker( | ||||
|     ) | ||||
|   ), | ||||
|   // highlight-next-line | ||||
|   {type: "module"} // second argument to Worker constructor | ||||
|   { type: "module" } // second argument to Worker constructor | ||||
| ); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Downloading a Remote File | ||||
| ## Live Demos | ||||
| 
 | ||||
| ### Downloading a Remote File | ||||
| 
 | ||||
| :::note fetch in Web Workers | ||||
| 
 | ||||
| @ -252,7 +265,7 @@ self.addEventListener('message', async(e) => { | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Creating a Local File | ||||
| ### Creating a Local File | ||||
| 
 | ||||
| :::caution Writing files from Web Workers | ||||
| 
 | ||||
| @ -357,7 +370,7 @@ self.addEventListener('message', async(e) => { | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## User-Submitted File | ||||
| ### User-Submitted File | ||||
| 
 | ||||
| :::note FileReaderSync | ||||
| 
 | ||||
| @ -375,9 +388,9 @@ sequenceDiagram | ||||
|   actor User | ||||
|   participant Page | ||||
|   participant Worker | ||||
|   User->>Page: click button | ||||
|   User->>Page: submit file | ||||
|   activate Page | ||||
|   Page->>Worker: send URL | ||||
|   Page->>Worker: send pointer | ||||
|   deactivate Page | ||||
|   activate Worker | ||||
|   Note over Worker: fetch file | ||||
| @ -454,7 +467,7 @@ self.addEventListener('message', (e) => { | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Streaming Write | ||||
| ### Streaming Write | ||||
| 
 | ||||
| A more general discussion, including row-oriented processing demos, is included | ||||
| in the ["Large Datasets"](/docs/demos/stream#browser) demo. | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/storageapi/lstorage.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/storageapi/lstorage.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 99 KiB | 
		Loading…
	
		Reference in New Issue
	
	Block a user